当前位置: 首页 > news >正文

门户网站建设 存在的问题/公司网站与推广

门户网站建设 存在的问题,公司网站与推广,长春网站建设那家好,html做音乐网站模板常见限流算法 固定窗口算法 在固定的时间窗口下进行计数,达到阈值就拒绝请求。固定窗口如果在窗口开始就打满阈值,窗口后半部分进入的请求都会拒绝。 滑动窗口算法 在固定窗口的基础上,窗口会随着时间向前推移,可以在时间内平滑控…

常见限流算法

  1. 固定窗口算法

    在固定的时间窗口下进行计数,达到阈值就拒绝请求。固定窗口如果在窗口开始就打满阈值,窗口后半部分进入的请求都会拒绝。

  2. 滑动窗口算法

    在固定窗口的基础上,窗口会随着时间向前推移,可以在时间内平滑控制流量,解决固定窗口出现的突发流量问题。

  3. 漏斗算法

    请求来了先进入漏斗,漏斗以恒定的速率放行请求。

  4. 令牌桶算法

    在令牌桶中,以恒定的速率放入令牌,令牌桶也有一定的容量,如果满了令牌就无法放进去了。拿到令牌的请求通过,并消耗令牌,如果令牌桶中令牌为空,则会丢弃该请求。

redis实现滑动窗口算法

当有请求来的时候记录时间戳,统计窗口内请求的数量时只需要统计redis中记录的数量。可以使用redis中的zset结构来存储。key可以设置为请求的资源名,同时根据限流的对象,往key中加入限流对象信息。比如根据ip限制访问某个资源的流量,可以使用方法名+ip作为key。score设置为时间戳。value则可以根据请求参数等信息生成MD5,或者直接生成UUID来存入,防止并发时多个请求存入的score和value一样导致只存入一个数据。

步骤如下:

  1. 定义时间窗口
  2. 请求到来,丢弃时间窗口之外的数据,ZREMRANGEBYSCORE KEYS[i], -inf, window_start
  3. 判断时间窗口内的请求个数是否达到阈值。ZCARD KEYS[i] 要小于阈值
  4. 如果小于则通过zadd加入,超过则返回不放行

lua脚本:

local window_start = tonumber(ARGV[1])- tonumber(ARGV[2])
redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', window_start)
local current_requests = redis.call('ZCARD', KEYS[1])
if current_requests < tonumber(ARGV[3]) thenredis.call('ZADD', KEYS[1], tonumber(ARGV[1]), ARGV[4])return 1
elsereturn 0
end

java通过注解+切面实现限流

在java中,我们的需求是对资源可以进行多种规则的限流。注解可以定义不同类型的限流,如:全局限流,根据IP限流,根据用户限流。对每种类型的限流可以在一个注解中定义多个限流规则。

整体效果如下:

@RateLimiter(rules = {@RateLimitRule(time = 50,count = 100),@RateLimitRule(time = 20,count = 10)}, type = LimitType.IP)
@RateLimiter(rules = {@RateLimitRule(time = 60,count = 1000)}, type = LimitType.DEFAULT)
public void update(){}

定义注解

定义了三个注解:

  1. RateLimiter:限流注解
  2. RateLimitRule:限流规则
  3. RateLimiters:存放多个限流注解的容器,为了可以重复使用该注解

RateLimiter:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 支持重复注解
@Repeatable(value = RateLimiters.class)
public @interface RateLimiter {/*** 限流键前缀** @return*/String key() default "rate_limit:";/*** 限流规则** @return*/RateLimitRule[] rules() default {};/*** 限流类型** @return*/LimitType type() default LimitType.DEFAULT;
}

RateLimitRule:

public @interface RateLimitRule {/*** 时间窗口, 单位秒** @return*/int time() default 60;/*** 允许请求数** @return*/int count() default 100;
}

RateLimiters:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RateLimiters {RateLimiter[] value();
}

改造lua脚本

在实现切面之前,我们需要对lua脚本进行改造。我们的需求对资源可以进行多种规则的限流。根据限流类型和限流规则可以组合出不同的key,比如我们要对某个资源进行以下规则限流:全局限流(60s,1000次; 600s,5000次),根据ip限流(2s,5次)。

根据这些规则我们就需要使用3个zset分别来存放请求记录。并且当三个规则都没达到阈值时才放行请求,否则拒绝请求。

对lua脚本改造,支持多个key。

 
local flag = 1
for i = 1, #KEYS dolocal window_start = tonumber(ARGV[1])- tonumber(ARGV[(i-1)*3+2])redis.call('ZREMRANGEBYSCORE', KEYS[i], '-inf', window_start)local current_requests = redis.call('ZCARD', KEYS[i])if current_requests < tonumber(ARGV[(i-1)*3+3]) thenelseflag = 0end
end
if flag == 1 thenfor i = 1, #KEYS doredis.call('ZADD', KEYS[i], tonumber(ARGV[1]), ARGV[(i-1)*3+4])end
end
return flag

定义切面

定义一个切面实现限流逻辑:RateLimiterAspect

首先定义切点,由于我们可以重复使用注解,所以需要把RateLimiter和RateLimiters都定义为切点

@Pointcut("@annotation(com.imgyh.framework.annotation.RateLimiter)")
public void rateLimiter() {
}@Pointcut("@annotation(com.imgyh.framework.annotation.RateLimiters)")
public void rateLimiters() {
}

在前置通知中实现限流逻辑:

主要流程如下:

  1. 把所有的RateLimiter都拿到,解析出限流规则和限流类型
  2. 根据限流规则和限流类型,获取所有的key和参数,为调用lua脚本做准备
  3. 调用lua脚本,根据返回值判断是否放行请求
// 定义切点之前的操作
@Before("rateLimiter() || rateLimiters()")
public void doBefore(JoinPoint point) {try {// 从切点获取方法签名MethodSignature signature = (MethodSignature) point.getSignature();// 获取方法Method method = signature.getMethod();String name = point.getTarget().getClass().getName() + "." + signature.getName();// 获取日志注解RateLimiter rateLimiter = method.getAnnotation(RateLimiter.class);RateLimiters rateLimiters = method.getAnnotation(RateLimiters.class);List<RateLimiter> limiters = new ArrayList<>();if (ObjectUtils.isNotNull(rateLimiter)) {limiters.add(rateLimiter);}if (ObjectUtils.isNotNull(rateLimiters)) {limiters.addAll(Arrays.asList(rateLimiters.value()));}if (!allowRequest(limiters, name)) {throw new ServiceException("访问过于频繁,请稍候再试");}} catch (ServiceException e) {throw e;} catch (Exception e) {throw new RuntimeException("服务器限流异常,请稍候再试");}
}/*** 是否允许请求** @param rateLimiters 限流注解* @param name         方法全名* @return 是否放行*/
private boolean allowRequest(List<RateLimiter> rateLimiters, String name) {List<String> keys = getKeys(rateLimiters, name);Object[] args = getArgs(rateLimiters);Object res = redisTemplate.execute(limitScript, keys, args);return ObjectUtils.isNotNull(res) && (Long) res == 1L;
}/*** 获取限流的键** @param rateLimiters 限流注解* @param name         方法全名* @return*/
private List<String> getKeys(List<RateLimiter> rateLimiters, String name) {List<String> keys = new ArrayList<>();for (RateLimiter rateLimiter : rateLimiters) {String key = rateLimiter.key();RateLimitRule[] rules = rateLimiter.rules();LimitType type = rateLimiter.type();StringBuilder sb = new StringBuilder();sb.append(key).append(name);if (LimitType.IP == type) {String ipAddr = IpUtils.getIpAddr();sb.append("_").append(ipAddr);} else if (LimitType.USER == type) {Long userId = SecurityUtils.getUserId();sb.append("_").append(userId);}for (RateLimitRule rule : rules) {int time = rule.time() * 1000;int count = rule.count();StringBuilder builder = new StringBuilder(sb);builder.append("_").append(time).append("_").append(count);keys.add(builder.toString());}}return keys;
}/*** 获取需要的参数** @param rateLimiters 限流注解* @return*/
private Object[] getArgs(List<RateLimiter> rateLimiters) {List<Object> args = new ArrayList<>();args.add(System.currentTimeMillis());for (RateLimiter rateLimiter : rateLimiters) {RateLimitRule[] rules = rateLimiter.rules();for (RateLimitRule rule : rules) {int time = rule.time() * 1000;int count = rule.count();args.add(time);args.add(count);args.add(IdUtils.fastSimpleUUID());}}return args.toArray();
}

实例demo演示

demo源码仓库:github.com/imgyh/devel…

定义接口,并添加限流注解。

限制对某个用户只能1s中访问2次。对接口整体10s中访问50次,60秒访问100次。

当某个用户一秒钟请求超过两次时,抛出异常。

参考资源

  1. Hollis,《Java面试宝典》
  2. 一文搞懂高频面试题之限流算法,从算法原理到实现,再到对比分析

相关文章:

Redis实现滑动窗口限流

常见限流算法 固定窗口算法 在固定的时间窗口下进行计数&#xff0c;达到阈值就拒绝请求。固定窗口如果在窗口开始就打满阈值&#xff0c;窗口后半部分进入的请求都会拒绝。 滑动窗口算法 在固定窗口的基础上&#xff0c;窗口会随着时间向前推移&#xff0c;可以在时间内平滑控…...

SQL Server查询计划(Query Plan)——XML查询计划

​​​​​​6.4.3. XML查询计划 SQL Server中,除了通过GUI工具和相关命令获取图形及文本查询计划外,我们还可以通过相关命令获取XML格式的查询计划,这里惯称其为XML查询计划。 SQL Server 2005版本引入了XML查询计划的新特性,其充分吸收了图形及文本查询计划的优势所在,…...

【day02】每天三道 java后端面试题:Java、C++和Go的区别 | Redis的特点和应用场景 | 计算机网络七层模型

文章目录 1. Java、C和 Go 语言的区别&#xff0c;各自的优缺点&#xff1f;2. 什么是Redis&#xff1f;Redis 有哪些特点&#xff1f; Redis有哪些常见的应用场景&#xff1f;3. 简述计算机网络七层模型和各自的作用&#xff1f; 1. Java、C和 Go 语言的区别&#xff0c;各自的…...

【Flink状态管理(八)】Checkpoint:CheckpointBarrier对齐后Checkpoint的完成、通知与对学习状态管理源码的思考

文章目录 一. 调用StreamTask执行Checkpoint操作1. 执行Checkpoint总体代码流程1.1. StreamTask.checkpointState()1.2. executeCheckpointing1.3. 将算子中的状态快照操作封装在OperatorSnapshotFutures中1.4. 算子状态进行快照1.5. 状态数据快照持久化 二. CheckpointCoordin…...

防御保护第八、九、十、十一天笔记

一、内容安全 1、DFI和DPI技术 --- 深度检测技术 DPI是一种基于应用层的流量检测和控制技术&#xff0c;它会对流量进行拆包&#xff0c;分析包头和应用层的内容&#xff0c;从而识别应用程序和应用程序的内容。这种技术增加了对应用层的分析&#xff0c;识别各种应用&#xf…...

【TypeScript基础知识点】的讲解

TypeScript基础知识点 TypeScript基础知识点 TypeScript基础知识点 TypeScript 是一种由 Microsoft 开发和维护的开源编程语言&#xff0c;它是 JavaScript 的一个超集&#xff0c;添加了可选的静态类型和基于类的面向对象编程&#xff0c;以下是一些 TypeScript 的基础知识点…...

牛客周赛 Round 34 解题报告 | 珂学家 | 构造思维 + 置换环

前言 整体评价 好绝望的牛客周赛&#xff0c;彻底暴露了CF菜菜的本质&#xff0c;F题没思路&#xff0c;G题用置换环骗了50%, 这大概是唯一的亮点了。 A. 小红的字符串生成 思路: 枚举 a,b两字符在相等情况下比较特殊 a, b input().split() if a b:print (2)print (a)pri…...

LeetCode13 罗马数字转整数

题目 罗马数字包含以下七种字符: I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&…...

【Hudi】Upsert原理

17张图带你彻底理解Hudi Upsert原理 1.开始提交&#xff1a;判断上次任务是否失败&#xff0c;如果失败会触发回滚操作。然后会根据当前时间生成一个事务开始的请求标识元数据。2.构造HoodieRecord Rdd对象&#xff1a;Hudi 会根据元数据信息构造HoodieRecord Rdd 对象&#xf…...

信息系统服务:演绎数字时代的征程

信息系统服务作为数字化时代的基石&#xff0c;已经在人类社会的各个领域发挥着重要作用。本文将从信息系统服务的起源、发展和演化过程&#xff0c;通过生动的例子和准确客观的历史事实&#xff0c;探讨信息系统服务对人类社会的影响与变革。 1. 起源&#xff1a;信息处理的初…...

rust连接postgresql数据库

引入crate&#xff1a; postgres "0.19.7" use postgres::{Client, NoTls, error::Error};fn main() -> Result<(), Error> {let mut client Client::connect("hostlocalhost port5432 dbnamexxxxdb userpostgres passwordxxxxxx", NoTls).un…...

[面试] 什么是死锁? 如何解决死锁?

什么是死锁 死锁&#xff0c;简单来说就是两个或者多个的线程在执行的过程中&#xff0c;争夺同一个共享资源造成的相互等待的现象。如果没有外部干预线程会一直阻塞下去. 导致死锁的原因 互斥条件&#xff0c;共享资源 X 和 Y 只能被一个线程占用; 请求和保持条件&#xf…...

网络原理 HTTP _ HTTPS

回顾 我们前面介绍了HTTP协议的请求和响应的基本结构 请求报文是由首行请求头空行正文来组成的 响应报文是由首行形影头空行响应正文组成的 我们也介绍了一定的请求头之中的键值对的属性 Host,Content-type,Content-length,User-agent,Referer,Cookie HTTP协议中的状态码 我们先…...

软件实际应用实例,茶楼收银软件管理系统操作流程,茶室计时计费会员管理系统软件试用版教程

软件实际应用实例&#xff0c;茶楼收银软件管理系统操作流程&#xff0c;茶室计时计费会员管理系统软件试用版教程 一、前言 以下软件以 佳易王茶社计时计费管理系统软件V17.9为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、计时计费&…...

网络安全“三保一评”深度解析

“没有网络安全就没有国家安全”。近几年&#xff0c;我国法律法规陆续发布实施&#xff0c;为承载我国国计民生的重要网络信息系统的安全提供了法律保障&#xff0c;正在实施的“3保1评”为我国重要网络信息系统的安全构筑了四道防线。 什么是“3保1评”&#xff1f; 等保、分…...

IDA使用-2023CICSN华中赛区pwn题逆向为例

文章目录 相关字节标识导入函数和导出函数找程序入口函数选项设置重命名CISCN2023华中赛区分区赛AWDIDA源码main 构造结构体sub_141B() 打开局部变量类型的视图增加变量类型重新定义变量类型再次设置变量类型并重新定义再次设置变量类型并重新定义再次设置变量类型并重新定义 设…...

安装虚拟机出现的一些问题

1、在重新打开软件之后出现闪退 解决&#xff1a;[WSL] 解决nsenter: cannot open /proc/320/ns/time: No such file or directory 问题 小白向-CSDN博客2、重新启动xrdp服务命令 解决&#xff1a; sudo systemctl restart xrdp3、将端口从3389改为3390&#xff0c;因为此前…...

Git+py+ipynb Usage

0.default config ssh-keygen -t rsa #之后一路回车,当前目录.ssh/下产生公私钥 cat ~/.ssh/id_rsa.pub #复制公钥到账号 git config --global user.email account_email git config --global user.name account_namebug of ipynb TqdmWarning: IProgress not found. Please …...

eBPF实践篇之环境搭建

文章目录 前言实验环境前置知识配置开发环境最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;本次我们学习一下eBPF&#xff0c;我们基于libbpf-bootstrap来进行我们的eBPF程序开发&#x1f917; 实验环境 一台Debian12操作系统的计算机&#xff0c;我使用的是Debian12.…...

机器学习科普及学习路线

机器学习是一种让计算机系统通过从数据中学习来改进性能的方法。它的学习方法主要包括监督学习、无监督学习和强化学习。下面我将详细解释机器学习的概念、学习方法和学习路线。 1. 机器学习概念&#xff1a; 机器学习是一种人工智能的分支&#xff0c;旨在使计算机系统能够从…...

如何在本地电脑部署HadSky论坛并发布至公网可远程访问【内网穿透】

文章目录 前言1. 网站搭建1.1 网页下载和安装1.2 网页测试1.3 cpolar的安装和注册 2. 本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09;2.4 公网访问测试 总结 前言 经过多年的基础…...

Spring Boot 笔记 025 主界面

1.1 路由搭建 1.1.1 安装vue router npm install vue-router4 1.1.2 在src/router/index.js中创建路由器&#xff0c;并导出 import { createRouter, createWebHistory } from vue-router//导入组件 import LoginVue from /views/Login.vue import LayoutVue from /views/La…...

(done) Positive Semidefinite Matrices 什么是半正定矩阵?如何证明一个矩阵是半正定矩阵? 可以使用特征值

参考视频&#xff1a;https://www.bilibili.com/video/BV1Vg41197ew/?vd_source7a1a0bc74158c6993c7355c5490fc600 参考资料(半正定矩阵的定义)&#xff1a;https://baike.baidu.com/item/%E5%8D%8A%E6%AD%A3%E5%AE%9A%E7%9F%A9%E9%98%B5/2152711?frge_ala 看看半正定矩阵的…...

七、矩阵的初等变换

目录 -1. 介绍 0、增广矩阵&#xff1a; 1、初等变换的性质&#xff1a; ​编辑2、矩阵初等变换的分类&#xff1a; 2.1 普通的行阶梯矩阵&#xff1a; 2.2 、行最简形矩阵&#xff1a; 2.3、标准形矩阵&#xff1a; 3、初等变换的定理&#xff1a; 4、初等变换的应用&…...

CSS background-size

background-size 菜鸟教程 CSS3 background-size 属性 MDN Web 开发技术>CSS&#xff1a;层叠样式表>background-size CSS的background 背景图片自动适应元素大小,实现img的默认效果 background-size:100% 100%&#xff1b; 在CSS中&#xff0c;background-size属性用…...

【机器学习】特征工程之特征选择

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…...

Java中PDF文件传输有哪些方法?

专栏集锦&#xff0c;大佬们可以收藏以备不时之需&#xff1a; Spring Cloud 专栏&#xff1a;http://t.csdnimg.cn/WDmJ9 Python 专栏&#xff1a;http://t.csdnimg.cn/hMwPR Redis 专栏&#xff1a;http://t.csdnimg.cn/Qq0Xc TensorFlow 专栏&#xff1a;http://t.csdni…...

前后端分离Vue+ElementUI+nodejs蛋糕甜品商城购物网站95m4l

本文主要介绍了一种基于windows平台实现的蛋糕购物商城网站。该系统为用户找到蛋糕购物商城网站提供了更安全、更高效、更便捷的途径。本系统有二个角色&#xff1a;管理员和用户&#xff0c;要求具备以下功能&#xff1a; &#xff08;1&#xff09;用户可以修改个人信息&…...

Pytorch 复习总结 3

Pytorch 复习总结&#xff0c;仅供笔者使用&#xff0c;参考教材&#xff1a; 《动手学深度学习》Stanford University: Practical Machine Learning 本文主要内容为&#xff1a;Pytorch 多层感知机。 本文先介绍了多层感知机的用法&#xff0c;再就训练过程中经常出现的过拟…...

2024年危险化学品经营单位主要负责人证考试题库及危险化学品经营单位主要负责人试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年危险化学品经营单位主要负责人证考试题库及危险化学品经营单位主要负责人试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特…...