服务限流方案总结

news2024/11/27 3:13:09

流控作用

一般的做后台服务的,都会接触到流控,一般的场景就是在流量异常,比如遭受攻击的时候,保障服务不过载,在可支持的范围内提供稳定的服务。比如我们的服务支持100QPS,当一下子来了1000个请求的时候,我们在可服务的范围内,每秒处理100个请求,这样在牺牲一些响应时效性的时候,可以保证服务不会crash。

单机限流(guava的RateLimiter)

示例

Guava给我们提供了好用的流控工具,简单使用场景如下

    private static RateLimiter rateLimiter = RateLimiter.create(5);

    public static void main(String[] args) throws InterruptedException {
        while (true) {
            get(1);
        }
    }

    private static void get(int permits) {
        rateLimiter.acquire(permits);
        System.out.println(System.currentTimeMillis());
    }

运行这个简单的代码片段,从打印的时间戳可以看出来,每200ms打印一次,即正好控制QPS为5,同时保证稳定的速率。简单来说,就是当有大量请求进来的时候,限制请求的频率,维持其在一个稳定的区间。而其具体的方法,简单来说就是,根据上次处理的时间戳和允许的每秒允许的请求,来决定下次可以执行的时间。

原理

RateLimiter主要是利用了一个令牌桶的算法,系统以恒定的速率产生令牌(permit),当来一个请求的时候,会请求一个或者多个令牌,当且仅当系统有这么多个令牌的时候,请求才被允许执行,否则就一直等待令牌的生成。也就是以固定的频率向桶中放入令牌,例如一秒钟10枚令牌,实际业务在每次响应请求之前都从桶中获取令牌,只有取到令牌的请求才会被成功响应,获取的方式有两种:阻塞等待令牌或者取不到立即返回失败。

令牌同简单示意图

核心方法

方法说明

public static RateLimiter create(double permitsPerSecond)

该方法会创建一个RateLimiter实例,其每秒产生permitsPerSecond个令牌

public double acquire(int permits)

该方法是用于获取N个令牌的方法,如果系统内令牌不够,则一直等待直到有足够令牌可用

public boolean tryAcquire(int permits, Duration timeout)

该方法用户获取另外,如果在timeout时间内可以获取到足够的令牌,则等待,否则直接返回false

方法原理

  • 保持分发的速率,以一定速率分发令牌,比如我们设置permitsPerSecond为500的话,则每2毫秒产生一个令牌
  • 令牌会存储,若一定时间没有请求,可用令牌会存储下来,当然会有一个上限值,当下次来请求的时候,优先使用现有的存储的令牌
  • 会有一个nextFreeTicketMicros来记录下次有可用令牌的时间戳,在这个时间之前,所有的请求均不能通过

guava依赖:

<dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
      <version>18.0</version>
    </dependency>

集群限流

下面介绍几种服务集群的限流方案:

Nginx 限流

Nginx 官方提供的限速模块使用的是 漏桶算法,保证请求的实时处理速度不会超过预设的阈值,主要有两个设置:

  • limit_req_zone: 限制 IP 在单位时间内的请求数
  • limit_req_conn: 限制同一时间链接数

Redis 限流

分布式服务接口限流,通常会结合Redis来做,根据 Redis 提供的 incr 命令,在规定的时间窗口,容许经过的最大请求数。例如如果要设置每1s只能通过的请求数,通常会使用redis incr再设置过期时间,例如使用的键值对业务标识:秒级时间戳,并使用incr命令,每来一次请求,就增加1,然后与规则进行对比,并为键设置过期时间,例如1分钟。

Incr 命令介绍:

Redis Incr 命令将 key 中储存的数字值增一。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。且将key的有效时间设置为长期有效 。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。本操作的值限制在 64 位(bit)有符号数字表示之内。因为Redis没有专用的整数类型,所以在内存中是以字符串的形式存储的。

限流:利用redis的incr命令可以实现一般的限流操作。如限制某接口每秒请求次数上限1000次

    /**
     * 1秒内最大1000次
     * @param key  可以设计为业务标识及接口标识+秒级时间戳组合。
     * @param expireMillis 过期时间60s
     * @return
     */
    public Boolean limiter(String key, Long expireMillis) {
        Long count = redisTemplate.opsForValue().increment(key, INCREMENT_STEP);
        if (1 == count) {
            redisTemplate.expire(key, expireMillis, TimeUnit.SECONDS);
        }
        if (count > 1000) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

increment函数解释:在key下的value整型数基础上加delta值。

	/**
	 * Increment an integer value stored as string value under {@code key} by {@code delta}.
	 *
	 * @param key must not be {@literal null}.
	 * @param delta
	 * @return {@literal null} when used in pipeline / transaction.
	 * @see <a href="https://redis.io/commands/incrby">Redis Documentation: INCRBY</a>
	 */
	@Nullable
	Long increment(K key, long delta);

 

分布式滑动窗口限流

Kong 官方提供了一种分布式滑动窗口算法的设计, 目前支持在 Kong 上作集群限流配置。它经过集中存储每一个滑动窗口和 consumer 的计数,从而支持集群场景。这里推荐一个 Go 版本的实现: slidingwindow

其余

另外业界在分布式场景下,也有 经过 Nginx+Lua 和 Redis+Lua 等方式来实现限流

总结

        本文主要在学习和调研高并发场景下的限流方案的总结。目前业界流行的限流算法包括计数器、漏桶、令牌桶和滑动窗口, 每种算法都有本身的优点,实际应用中能够根据本身业务场景作选择,而分布式场景下的限流方案,也基本经过以上限流算法来实现。在高并发下流量控制的一个原则是:先让请求先到队列,并作流量控制,不让流量直接打到系统上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/529188.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全景 I 0基础学习VR全景制作,平台篇第22篇 热点功能—作品功能操作

本期为大家带来蛙色VR平台&#xff0c;热点功能—作品功能操作。 功能位置示意 热点&#xff0c;指在全景作品中添加各种类型图标的按钮&#xff0c;引导用户通过按钮产生更多的交互&#xff0c;增加用户的多元化体验。 作品热点&#xff0c;即全景项目跳转热点&#xff0c;可与…

您使用的ChatGPT错了!以下是如何领先于 99% 的 ChatGPT 用户

我们大多数人都错误地使用了 ChatGPT&#xff1a; 错误1&#xff1a;不在提示中包含示例。 错误2&#xff1a;忽略通过角色控制 ChatGPT 的行为。 错误3&#xff1a;让 ChatGPT 猜测内容&#xff0c;而不是向它提供一些信息。 通过3类有用的prompt工程掌握 ChatGPT的使用。 …

leetcode 1259. 不相交的握手

1259. 不相交的握手 提示 困难 33 company 字节跳动 company 苹果 Apple company 亚马逊 偶数 个人站成一个圆&#xff0c;总人数为 num_people 。每个人与除自己外的一个人握手&#xff0c;所以总共会有 num_people / 2 次握手。 将握手的人之间连线&#xff0c;请你返回连线…

十二、Feign客户端整合Hystrix服务保护

目录 1、项目pom文件中引入feign客户端依赖 2、编写feign客户端接口&#xff0c;并配置fallback回调方法的类 3、编写controller&#xff0c;使用feign客户端进行RPC远程过程调用 4、实现feign客户端接口方法&#xff0c;并实现feign客户端接口中的每个接口方法作为fallbac…

十一、Hystrix服务保护

目录 服务雪崩相关概念简述 服务的雪崩效应 造成服务雪崩的原因 服务雪崩最终的结果 防止服务雪崩的方法 一、服务降级 1、引入Hystrix 服务保护依赖 2、基于注解HystrixCommand使用Hystrix 2.1、在需要进行服务保护的方法上添加注解HystrixCommand&#xff0c;并指定…

公有云云硬盘(EBS)有效范围内扩容/存储规格变更指导手册

一、背景 某公有云环境中,云主机直连的云硬盘存储某数据库数据,随着数据的积累,大约10亿多条数据,云硬盘急需扩容,但前期规划云硬盘未开启lvm卷,且当前存储容量未达EBS容量限制,最大可达32T,因此觉得采用EBS规格变更的方式来实现主机存储的扩容; 二、注意点: 1)过…

Matlab入门教程|002球的体积问题

写给Matlab小白的教程。如果你已经安装了Matlab&#xff0c;手头有一堆Matlab教程&#xff0c;面对书中一堆术语和命令不知所措&#xff0c;那么&#xff0c;请看本教程&#xff0c;从零开始&#xff0c;快速上手。 1 本文要点 初等代数计算&#xff1a;求函数值&#xff0c;求…

算法小技巧:空间换时间,时间换空间?

前言&#xff1a;小细节&#xff0c;大道理&#xff0c;思路在前&#xff0c;代码在后。 名词解释&#xff1a; 算法效率&#xff1a;往往由时间效率和空间效率两个方面决定。 时间效率&#xff1a;时间效率被称为时间复杂度&#xff0c;指的是算法执行过程耗费的时间…

英文论文(sci)解读复现【NO.10】宁夏酿酒葡萄病虫害智能检测平台设计

此前出了目标检测算法改进专栏&#xff0c;但是对于应用于什么场景&#xff0c;需要什么改进方法对应与自己的应用场景有效果&#xff0c;并且多少改进点能发什么水平的文章&#xff0c;为解决大家的困惑&#xff0c;此系列文章旨在给大家解读发表高水平学术期刊中的 SCI论文&a…

龙蜥产品生态总监做客 InfoQ:后 CentOS 时代,国产操作系统能否扛起大旗?

随着 CentOS 全面停服即将进入尾声&#xff0c;企业选择一款既可保障系统稳定运行&#xff0c;又可提供专业技术支持的操作系统迁移显得尤为重要。那么&#xff0c;现存的 CentOS 以及衍生版用户或将面临哪些风险&#xff1f;一套完整的迁移方案应该包括哪些步骤&#xff1f;在…

Shap-E:3D资产的生成式AI大模型

OpenAI 刚刚发布了 Shap-E&#xff0c;这是一种基于文本提示和图像创建 3D 资产的生成模型&#xff0c;能够生成带纹理的网格和神经辐射场 &#xff0c;从而实现各种 3D 输出。 推荐&#xff1a;用 NSDT设计器 快速搭建可编程3D场景。 在本教程中&#xff0c;我们将引导你在 Go…

【云原生进阶之PaaS中间件】第一章Redis-2.3.1主从复制部署模式

1 部署架构 Redis在日常部署的时候&#xff0c;可以有多种部署模式&#xff1a;单机、主从、哨兵、集群&#xff08;分区分片&#xff09;&#xff0c;因此本文将对上面这四种模式进行详细的讲解&#xff0c;特别是集群模式将进行最细致的讲解&#xff08;现行普遍使用的方式&a…

Cpolar内网穿透本地MariaDB数据库

Cpolar内网穿透本地MariaDB数据库 cpolar内网穿透本地MariaDB数据库&#xff0c;实现外公网环境下使用navicat图形化工具远程连接本地内网的MariaDB数据库 配置MariaDB数据库 安装MariaDB数据库 进入MariaDB数据库官网https://mariadb.com/downloads/community/,然后下载相应的…

知行之桥2023版本发布

我们很高兴地宣布知行之桥EDI系统2023版本正式发布。本次发布的知行之桥2023版&#xff08;版本号&#xff1a;8518&#xff09;包含了新的企业级功能&#xff0c;以下是新版本的一些亮点&#xff1a; 1.新增了概览页面&#xff0c;支持查看消息的整个生命周期&#xff0c;添加…

MySQL基础(三十三)MySQL事务日志

事务有4种特性&#xff1a;原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢&#xff1f; 事务的隔离性由 锁机制 实现。而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。 REDO LOG 称为 重做日志 &#xff0c;提供再写入操…

深度学习之神经网络是如何自行学习的?

大家好&#xff0c;我是带我去滑雪&#xff01; 深度学习算法是一种神经网络&#xff0c;而神经网络就是数据结构的图形结构&#xff0c;函数集的运算是向量和矩阵运算&#xff0c;调整函数集的参数需要使用微分和偏微分来找出最优解。深度学习可以通过几何学来进行解释&#x…

Excel的“升级版本”, 终于在2023年找到,替代Office包里的Access

Access的用户基数很大 首先&#xff0c;你要明白的是&#xff0c;Access是一款办公软件&#xff0c;其次才是一个数据库&#xff01; 之所以一直以来被微软放在Office的包里&#xff0c;没有被淘汰&#xff0c;是因为Access在Excel处理大数据时崩溃的时候&#xff0c;面向很多…

本机连接aws的ec2时报错:所选用户的用户密钥未在远程主机上注册

引言 由于工作的需要&#xff0c;所以需要去学习下AWS相关的知识&#xff0c;所以自己注册了一个AWS的账号去进行学习。 问题发现 按照启动ec2实例的步骤&#xff1a;选择镜像->选择系统配置->配置密钥对->配置安全组->设置存储卷大小->启动实例 在上述操作…

237:vue+openlayers绘制多边形,生成geojson数据,计算出面积

第237个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中绘制多边形形,利用Geojson的writeFeatures,来生成geojson格式的数据,然后使用turf.area来计算面积。这里面着重解决了在3857的坐标系下,将geojson文件的坐标转化为4326的状态。 直接复制下面的 vue…

短视频矩阵源码系统

短视频矩阵源码系统开发要则&#xff1a; 1. 需求分析&#xff1a;对短视频平台的需求进行全面分析&#xff0c;确立系统开发目标和方向。 2. 技术选型&#xff1a;选用最适合的技术开发短视频矩阵系统&#xff0c;如前端框架、数据库、服务器等。 3. 系统设计&#xff1a;按…