java八股-流量封控系统
文章目录
- 请求后台管理的频率-流量限制
- 流量限制的业务代码
- UserFlowRiskControlFilter
- 短链接中台的流量限制
- CustomBlockHandler
- 对指定接口限流
- UserFlowRiskControlConfiguration
- SentinelRuleConfig
请求后台管理的频率-流量限制
根据登录用户做出控制,比如 x 秒请求后管系统的频率最多 x 次。
实现原理也比较简单,通过 Redis increment 命令对一个数据进行递增,如果超过 x 次就会返回失败。这里有个细节就是我们的这个周期是 x 秒,需要对 Redis 的 Key 设置 x 秒有效期。
但是 Redis 中对于 increment 命令是没有提供过期命令的,这就需要两步操作,进而出现原子性问题。
lua脚本步骤:
- 递增key对应的访问次数
- 給该key设置过期时间TTL,TTL是限制时间内的秒数,
- 最后返回TTL内的访问次数
使用lua脚本保证原子性,这里主要的作用是记录在timeWindow秒限制内的访问次数AccessCnt。
其中timeWindow是多少多少秒,lua脚本返回值(是在timeWindow秒内)被访问了AccessCnt次,
-- 设置用户访问频率限制的参数
local username = KEYS[1]
local timeWindow = tonumber(ARGV[1]) -- 时间窗口,单位:秒-- 构造 Redis 中存储用户访问次数的键名
local accessKey = "short-link:user-flow-risk-control:" .. username-- 原子递增访问次数,并获取递增后的值
local currentAccessCount = redis.call("INCR", accessKey)-- 设置键的过期时间
redis.call("EXPIRE", accessKey, timeWindow)-- 返回当前访问次数
return currentAccessCount
流量限制的业务代码
UserFlowRiskControlFilter
package com.nageoffer.shortlink.admin.common.biz.user;import com.alibaba.fastjson2.JSON;
import com.google.common.collect.Lists;
import com.nageoffer.shortlink.admin.common.convention.exception.ClientException;
import com.nageoffer.shortlink.admin.common.convention.result.Results;
import com.nageoffer.shortlink.admin.config.UserFlowRiskControlConfiguration;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scripting.support.ResourceScriptSource;import java.io.IOException;
import java.io.PrintWriter;
import java.util.Optional;import static com.nageoffer.shortlink.admin.common.convention.errorcode.BaseErrorCode.FLOW_LIMIT_ERROR;@Slf4j
@RequiredArgsConstructor
//用户流量封控过滤器
public class UserFlowRiskControlFilter implements Filter {private final StringRedisTemplate stringRedisTemplate;//用户流量封控配置器//这里这个UserFlowRiskControlConfiguration 在下面会有介绍的,反正这里的MaxAccessCount和time-window都是从Application.yaml里面读取到的private final UserFlowRiskControlConfiguration userFlowRiskControlConfiguration;private static final String USER_FLOW_RISK_CONTROL_LUA_SCRIPT_PATH = "lua/user_flow_risk_control.lua";@SneakyThrows@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();//设置加载到lua脚本对象redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(USER_FLOW_RISK_CONTROL_LUA_SCRIPT_PATH)));//设置lua脚本返回值类型是LongredisScript.setResultType(Long.class);String username = Optional.ofNullable(UserContext.getUsername()).orElse("other");Long result;try {result = stringRedisTemplate.execute(redisScript, Lists.newArrayList(username), userFlowRiskControlConfiguration.getTimeWindow());} catch (Throwable ex) {//设置为Throwable,防止捕获不到log.error("执行用户请求流量限制LUA脚本出错", ex);returnJson((HttpServletResponse) response, JSON.toJSONString(Results.failure(new ClientException(FLOW_LIMIT_ERROR))));return;}//如果访问次数Result>最大限制访问次数getMaxAccessCount,则返回流量限制异常if (result == null || result > userFlowRiskControlConfiguration.getMaxAccessCount()) {returnJson((HttpServletResponse) response, JSON.toJSONString(Results.failure(new ClientException(FLOW_LIMIT_ERROR))));return;}filterChain.doFilter(request, response);}private void returnJson(HttpServletResponse response, String json) throws Exception {response.setCharacterEncoding("UTF-8");response.setContentType("text/html; charset=utf-8");try (PrintWriter writer = response.getWriter()) {writer.print(json);}}
}
短链接中台的流量限制
使用sentinel来做中台的流量限制,首先引入依赖
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj</artifactId>
</dependency>
CustomBlockHandler
package com.nageoffer.shortlink.project.handler;import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.nageoffer.shortlink.project.common.convention.result.Result;
import com.nageoffer.shortlink.project.dto.req.ShortLinkCreateReqDTO;
import com.nageoffer.shortlink.project.dto.resp.ShortLinkCreateRespDTO;public class CustomBlockHandler {public static Result<ShortLinkCreateRespDTO> createShortLinkBlockHandlerMethod(ShortLinkCreateReqDTO requestParam, BlockException exception) {return new Result<ShortLinkCreateRespDTO>().setCode("B100000").setMessage("当前访问网站人数过多,请稍后再试...");}
}
sentinel技术对接口限流,超过指定的QPS之后会接口限流,Block住
下面的@SentinelResource里面的value是对保护资源的名称的指定,Blockhandler是保护资源用到的方法,BlockHandlerClass是保护资源用到的类Class

对指定接口限流
这里对接口限流,指定他的资源名称为create-short-link,以后带着这个名称,在SentinelRuleConfig(文章下面会介绍到位,也可以在目录里面快速定位到相关内容)里面会加入对这个资源的保护

UserFlowRiskControlConfiguration
Application.yaml和UserFlowRiskControlConfiguration
@Data
@Component
@ConfigurationProperties(prefix = "short-link.flow-limit") //从Application.yaml配置文件里面读取相应的数据信息
public class UserFlowRiskControlConfiguration {/*** 是否开启用户流量风控验证*/private Boolean enable;/*** 流量风控时间窗口,单位:秒*/private String timeWindow;/*** 流量风控时间窗口内可访问次数*/private Long maxAccessCount;
}
SentinelRuleConfig
定义接口规则
package com.nageoffer.shortlink.project.config;import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;import java.util.ArrayList;
import java.util.List;//解释一下,实现InitializingBean 接口并重写afterPropertiesSet是为了在Bean初始化完成之后,
//执行FlowRuleManager.loadRules(rules)把这个流量限制规则加入到位!!!!
@Component
public class SentinelRuleConfig implements InitializingBean { //@Overridepublic void afterPropertiesSet() throws Exception {List<FlowRule> rules = new ArrayList<>();FlowRule createOrderRule = new FlowRule();//通过对指定资源名称进行保护限流createOrderRule.setResource("create_short-link");//通过QPS限制createOrderRule.setGrade(RuleConstant.FLOW_GRADE_QPS);//QPS超过1就限流createOrderRule.setCount(1);rules.add(createOrderRule);FlowRuleManager.loadRules(rules);}
}
InitializingBean 接口,实现该接口的类需要提供一个 afterPropertiesSet 方法,该方法会在所有依赖注入完成后被调用
package org.springframework.beans.factory;public interface InitializingBean {void afterPropertiesSet() throws Exception;
}


相关文章:
java八股-流量封控系统
文章目录 请求后台管理的频率-流量限制流量限制的业务代码UserFlowRiskControlFilter 短链接中台的流量限制CustomBlockHandler 对指定接口限流UserFlowRiskControlConfigurationSentinelRuleConfig 请求后台管理的频率-流量限制 根据登录用户做出控制,比如 x 秒请…...
【WebRTC】Android SDK使用教学
文章目录 前言PeerConnectionFactoryPeerConnection 前言 最近在学习WebRTC的时候,发现只有JavaScript的API文档,找了很久没有找到Android相关的API文档,所以通过此片文章记录下在Android应用层如何使用WebRTC 本篇文章结合:【W…...
基于单片机的智能晾衣控制系统的设计与实现
摘要:本文是以 AT89C52 单片机为核心来实现智能晾衣控制系统。在这个系统中,雨水检测传感器是用来检测出雨的,而控制器将检测信号的变换,根据变换后的信号自动驱动直流电机将被风干 的棒收回,以便随时控制直流电机来实现晾衣;在光敏模块中检测昼夜的环境,自动控制晾衣杆…...
多人聊天室 NIO模型实现
NIO编程模型 Selector监听客户端不同的zhuangtai不同客户端触发不同的状态后,交由相应的handles处理Selector和对应的处理handles都是在同一线程上实现的 I/O多路复用 在Java中,I/O多路复用是一种技术,它允许单个线程处理多个输入/输出&…...
三、使用 Maven:命令行环境
文章目录 1. 第一节 实验一:根据坐标创建 Maven 工程1.1 Maven 核心概念:坐标1.2 实验操作1.3 Maven核心概念:POM1.4 Maven核心概念:约定的目录结构 2. 实验二:在 Maven 工程中编写代码2.1 主体程序2.2 测试程序 3. 执…...
Blender导入下载好的fbx模型像的骨骼像针戳/像刺猬
为什么我下载下来的骨骼模型和我自己绑定的模型骨骼朝向完全不一样 左边是下载的模型 右边是我自己绑定的模型 左边的模型刚刚感觉都是像针一样往外戳的,像刺猬一样那种。 解决方法勾选自动骨骼坐标系...
如何高效搭建智能BI数据分析系统
作为当今信息化时代,数据资产已经成为企业最为核心倚重的,自然企业也就面临来自于对内部这些数据的处理和分析。如何在大批量的数据当中提取有用信息,帮助企业做出智慧决策,是不少企业面临的问题。作为国内知名的BI数据分析系统服…...
第 6 章 Java 并发包中锁原理剖析Part one
目录 6.1 LockSupport 工具类 6.2 独占锁 ReentrantLock 的原理 获取锁 1.void lock() 方法 2.void lockInterruptibly() 方法 3.boolean tryLock() 方法 4.boolean tryLock(long timeout, TimeUnit unit) 方法 释放锁 6.1 Lo…...
使用 Canvas 绘制一个镂空的圆形区域
如果要实现一个类似人脸识别的界面,要求使用 canvas 进行绘制,中间镂空透明区域,背景是白色的画布。 技术方案: 首先,使用 canvas 绘制一个白色画布其次,使用 context.globalCompositeOperation 合成属性进…...
【Notepad++】---设置背景为护眼色(豆沙绿)最新最详细
在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。 【Notepad】---设置背景为护眼色…...
2024 数学建模国一经验分享
2024 数学建模国一经验分享 背景:武汉某211,专业:计算机科学 心血来潮,就从学习和组队两个方面指点下后来者,帮新人避坑吧 2024年我在数学建模比赛中获得了国一(教练说论文的分数是湖北省B组第一࿰…...
安全见闻2
安全见闻,犹如一座庞大而深邃的知识宝库,其中涵盖了形形色色的网络安全知识与错综复杂的网络技术体系。在当今数字化时代,这些领域的重要性不言而喻,它们不仅关乎个人信息的保护与隐私安全,更是支撑着整个互联网世界以…...
Web游戏开发指南:在 Phaser.js 中读取和管理游戏手柄输入
前言 Phaser.js 是一个广受欢迎的 HTML5 游戏框架,为开发者提供了创建跨平台 2D 游戏的强大工具。在现代游戏开发中,支持游戏手柄已成为提升玩家体验的重要方面。本文将详细介绍如何在 Phaser.js 中监听和处理游戏手柄的输入,帮助开发者为他…...
代码随想录32 动态规划理论基础,509. 斐波那契数,70. 爬楼梯,746. 使用最小花费爬楼梯。
1.动态规划理论基础 动态规划刷题大纲 什么是动态规划 动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规划是最有效的。 所以动态规划中每一个状态一定是由上一个状态推导出来的…...
记录一个Flutter 3.24单元测试点击事件bug
哈喽,我是老刘 这两天发现一个Flutter 3.24版本的单元测试的一个小bug,提醒大家注意一下。 老刘自己写代码十多年了,写Flutter也6年多了,没想到前两天在一个小小的BottomNavigationBar 组件上翻了车。 给大家分享一下事件的经过。…...
使用Python将 word文档转pdf文档
第一步:我们需要导入支持包 >pip install pywin32 如果下载速度比较慢的话,可以考虑使用国内镜像源。 第二步:我们需要导入文件,这里采用 input,用户填入路径后,直接获取路径下的word文档,实现批量转换…...
基于C#+SQLite开发数据库应用的示例
SQLite数据库,小巧但功能强大;并且是基于文件型的数据库,驱动库就是一个dll文件,有些开发工具 甚至不需要带这个dll,比如用Delphi开发,用一些三方组件;数据库也是一个文件,虽然是个文…...
Vue基本语法
Options API 选项式/配置式api 需要在script中的export default一个对象对象中可以包含data、method、components等keydata是数据,数据必须是一个方法(如果是对象,会导致多组件的时候,数据互相影响,因为对象赋值后&…...
芯片发展史
芯片的发展史可分为几个重要的阶段,从早期的真空管到现代的集成电路,反映了技术进步和创新的历程: 1. 真空管时代 (1904 - 1950年代) 真空管是20世纪初的电子元件,用于放大信号和开关,广泛应用在早期的收音机、电视机…...
我的知识图谱和Neo4j数据库的使用
知识图谱概述 知识图谱的含义 RDF与RDFS RDF(Resource Description Framework,资源描述框架)和RDFS(RDF Schema,RDF模式)是构建知识图谱的基础技术之一。它们提供了一种标准的方式来表示信息,…...
如何在GTA5在线模式中保护自己?YimMenu安全增强菜单完整指南
如何在GTA5在线模式中保护自己?YimMenu安全增强菜单完整指南 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/y…...
Orbit:革命性记忆增强平台的完整指南
Orbit:革命性记忆增强平台的完整指南 【免费下载链接】orbit Experimental spaced repetition platform for exploring ideas in memory augmentation and programmable attention 项目地址: https://gitcode.com/gh_mirrors/orbit1/orbit Orbit是一个革命性…...
5分钟上手:用VMagicMirror打造你的虚拟形象分身
5分钟上手:用VMagicMirror打造你的虚拟形象分身 【免费下载链接】VMagicMirror VRM Software for Windows to move avatar with minimal devices. 项目地址: https://gitcode.com/gh_mirrors/vm/VMagicMirror VMagicMirror是一款专为Windows设计的开源虚拟角…...
FModel完整指南:解锁虚幻引擎游戏资源的终极工具
FModel完整指南:解锁虚幻引擎游戏资源的终极工具 【免费下载链接】FModel Unreal Engine Archives Explorer 项目地址: https://gitcode.com/gh_mirrors/fm/FModel 你是否曾好奇《堡垒之夜》中的炫酷皮肤是如何制作的?或者想提取《Valorant》中的…...
保姆级教程:用Arduino IDE给ESP-01S烧录WebSocket固件,打造零配网智能开关
从零开始:用Arduino IDE为ESP-01S烧录WebSocket固件的完整指南 当你第一次拿到ESP-01S这个小巧的Wi-Fi模块时,可能会被它强大的功能和复杂的配置过程所困扰。特别是当你想要将它变成一个可以通过网页控制的智能开关时,固件烧录这个看似简单的…...
爬虫实战复盘:山东政务噪声数据逆向爬取踩坑全记录
爬虫实战复盘:山东政务噪声数据逆向爬取踩坑全记录 前言 近期在做全国各省市环境噪声实时数据爬虫、清洗、入库标准化项目,已经稳定跑通北京(静态HTML)、天津(SM3国密签名接口)两大站点。今天攻坚山东省噪声…...
Gradiant宣布完成E轮融资,公司估值达20亿美元,助力加快AI、半导体以及工业水务基建领域布局
随着Gradiant依托AI基建和先进制造业务实现业绩大幅增长,新资金将用于支持战略性并购、新一代技术研发以及上市筹备工作 Gradiant今日宣布完成E轮融资,公司估值达到20亿美元。本轮融资由Safar Partners和Hostplus Superannuation Fund领投,C…...
告别硬编码!在UE5 GAS里用曲线表格(Curve Table)动态管理RPG技能数值
告别硬编码!在UE5 GAS里用曲线表格(Curve Table)动态管理RPG技能数值 在开发RPG游戏时,技能数值的调整往往是一个频繁且耗时的过程。传统的硬编码方式不仅效率低下,还容易导致版本混乱。本文将介绍如何利用UE5的GAS系统…...
昇腾CANN shmem:把多张 NPU 的 HBM 变成一块全局内存
hccl 的通信模型是消息传递——发送方调 send,接收方调 recv,两边同步。hixl 的模型是单边推送——发送方调 put,接收方不用参与。shmem 是第三种模型:PGAS(Partitioned Global Address Space),…...
A/B测试还在用t检验?DeepSeek团队淘汰传统方法的4个关键转折点(含贝叶斯动态决策引擎实测对比)
更多请点击: https://intelliparadigm.com 第一章:A/B测试范式迁移的必然性 传统A/B测试长期依赖静态流量分配、固定实验周期与人工决策闭环,在现代高并发、多场景、实时反馈的业务系统中正面临三重结构性失配:实验吞吐量低、决策…...
