dubbo熔断限流_dubbo 限流 熔断-程序员宅基地

技术标签: 流量控制、熔断降级  

限流

  • 根据排队理论,具有延迟的服务随着请求量的不断提升,其平均响应时间也会迅速提升,为了保证服务的SLA(Service-Level Agreement 服务等级协议),有必要控制单位时间的请求量。这就是限流为什么愈发重要的原因。

分类

  • qps限流

    限制每秒处理请求数不超过阈值

  • 并发限流

    限制同时处理的请求数目。Java 中的 Semaphore(信号量) 是做并发限制的好工具,特别适用于资源有效的场景。

  • 单机限流

    Guava 中的 RateLimiter(内部采用令牌捅算法实现)。

  • 集群限流

    redis限流,计时器和计数器处理、key加秒为key

    nginx(+lua)前端限流,按照一定的规则如帐号、IP、系统调用逻辑等在Nginx层面做限流

算法

常见的限流算法有:令牌桶、漏桶。计数器也可以进行粗暴限流实现。

  • 漏桶算法
    在这里插入图片描述

  • 令牌桶算法
    在这里插入图片描述

实施方案

RPC限流(dubbo)

dubbo调用模型

连接调用图

在这里插入图片描述

调用时关键参数影响

参数名 作用范围 默认值 说明 备注
actives consumer 0 每服务消费者每服务每方法最大并发调用数 0表示不限制
connections consumer 对每个提供者的最大连接数,rmi、http、hessian等短连接协议表示限制连接数,dubbo等长连接协表示建立的长连接个数 dubbo时为1,即复用单链接
accepts provider 0 服务提供方最大可接受连接数 0表示不限制
iothreads provider cpu个数+1 io线程池大小(固定大小)
threads provider 200 业务线程池大小(固定大小)
executes provider 0 服务提供者每服务每方法最大可并行执行请求数 0表示不限制
tps provider 指定时间内(默认60s)最大的可执行次数,注意与executes的区别 默认不开启
queues provider 0 线程池队列大小,当线程池满时,排队等待执行的队列大小,建议不要设置,当线程程池时应立即失败,重试其它服务提供机器,而不是排队,除非有特殊需求。

分析

  1. 当consumer发起一个请求时,首先经过active limit(参数actives)进行方法级别的限制,其实现方式为CHM中存放计数器(AtomicInteger),请求时加1,请求完成(包括常)减1,如果超过actives则等待有其他请求完成后重试或者超时后失败;

  2. 从多个连接(connections)中选择一个连接发送数据,对于默认的netty实现来说,由于可以复用连接,默认一个连接就可以。不过如果你在压测,且只有一个consumer,一个provider,此时适当的加大connections确实能够增强网络传输能力。但线上业务由于有多个consumer多个provider,因此不建议增加connections参数;

  3. 连接到达provider时(如dubbo的初次连接),首先会判断总连接数是否超限(acceps),超过限制连接将被拒绝;

  4. 连接成功后,具体的请求交给io thread处理。io threads虽然是处理数据的读写,但io部分为异步,更多的消耗的是cpu,因此iothreads默认cpu个数+1是比较合理的设置,不建议调整此参数;

  5. 数据读取并反序列化以后,交给业务线程池处理,默认情况下线程池为fixed,且排队队列为0(queues),这种情况下,最大并发等于业务线程池大小(threads),如果希望有请求的堆积能力,可以调整queues参数。如果希望快速失败由其他节点处理(官方推荐方式),则不修改queues,只调整threads;

  6. execute limit(参数executes)是方法级别的并发限制,原理与actives类似,只是少了等待的过程,即受限后立即失败;

  7. tps,控制指定时间内(默认60s)的请求数。注意目前dubbo默认没有支持该参数

从上面的分析,可以看出如果 (consumer数 * actives > provider数 * threads) 且 (queues=0),则会存在部分请求无法申请到资源,重试也有很大几率失败。
当需要对一个接口的不同方法进行不同的并发控制时使用executes,否则调整threads就可以。

内容引用自 dubbo参数调优说明

dubbo filter

dubbo提供了多个和请求相关的filter 我们可以看到:ActiveLimitFilter ExecuteLimitFilter TPSLimiterFilter

  • ActiveLimitFilter

    @Activate(group = Constants.CONSUMER, value = Constants.ACTIVES_KEY)

作用于客户端,控制客户端同样的方法可同时运行的次数【即该方法的并发度】

```
dubbo:reference   
配置类:org.apache.dubbo.config.ReferenceConfig
actives:(int default 0) 每服务消费者每服务每方法最大并发调用数  2.0.5以上版本
```
```
dubbo:consumer
配置类: org.apache.dubbo.config.ConsumerConfig   
同时为 dubbo:reference 缺省值设置  
default.actives:(int default 0) 每服务消费者每服务每方法最大并发调用数 2.0.5以上版本
```
```
dubbo:provider
配置类: org.apache.dubbo.config.ProviderConfig
同时为 dubbo:service 和 dubbo:protocol 缺省值设置
default.actives:(int default 0) 每服务消费者每服务每方法最大并发调用数 2.0.5以上版本
```

actives:消费者端的最大并发调用限制,即当 Consumer 对一个服务的并发调用到上限后,新调用会阻塞直到超时,在方法上配置 dubbo:method 则针对该方法进行并发限制,在接口上配置 dubbo:service,则针对该服务进行并发限制
建议在 Provider 端配置的 Consumer 端属性
当超过了指定的active值之后该请求将等待前面的请求完成
何时结束呢?依赖于该方法的timeout 如果没有设置timeout的话 可能就是多个请求一直被阻塞然后等待随机唤醒吧
搭配timeout一起使用

  • ExecuteLimitFilter

    @Activate(group = Constants.PROVIDER, value = Constants.EXECUTES_KEY)

服务端限制

```
dubbo:service  
配置类:org.apache.dubbo.config.ServiceConfig  
executes:(int default 0) 服务提供者每服务每方法最大可并行执行请求数 2.0.5以上版
```
```
dubbo:provider  
配置类: org.apache.dubbo.config.ProviderConfig  
同时为 dubbo:service 和 dubbo:protocol 缺省值设置  
default.actives:(int default 0) 服务提供者每服务每方法最大可并行执行请求数 2.0.5以上版
```

一旦超出指定的数目直接报错 其实是指在服务端的并行度【需要注意这些都是指的是在单台服务上而不是整个服务集群】

  • TpsLimitFilter

    @Activate(group = Constants.PROVIDER, value = Constants.TPS_LIMIT_RATE_KEY)

同样作用在服务端 目的在于控制一段时间类中的请求数。dubbo没有默认支持。

```
使用TpsLimitFilter  
Dubbo框架并没有默认通过配置文件启动这个Filter,  
所以我们需要在classpath的META-INF/dubbo/目录下增加com.alibaba.dubbo.rpc.Filter文件  
tps=com.alibaba.dubbo.rpc.filter.TpsLimitFilter
就算加上了这个配置,其实也还是生效不了,我们的provider url需要有tps=xxx参数  

相关操作比较繁琐,dubbo没有提供默认实现自有其不推荐使用的理由
```

Dubbo之限流TpsLimitFilter源码分析–简书

dubbo Sentinel

Sentinel 限流、熔断、降级
Sentinel 开源地址:https://github.com/alibaba/Sentinel
Sentinel以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
Spring Cloud Alibaba
Sentinel 为 Dubbo 服务保驾护航
Sentinel

dubbo Hystrix

Hystrix 主要用于熔断降级

讨论
  • dubbo 全局限流实现方案及是否有必要?

API限流(http)

Nginx

对于Nginx接入层限流可以使用Nginx自带了两个模块:
连接数限流模块ngx_http_limit_conn_module和漏桶算法实现的请求限流模块ngx_http_limit_req_module。

  • ngx_http_limit_conn_module
    我们经常会遇到这种情况,服务器流量异常,负载过大等等。对于大流量恶意的攻击访问,会带来带宽的浪费,服务器压力,影响业务,往往考虑对同一个ip的连接数,并发数进行限制。ngx_http_limit_conn_module 模块来实现该需求。该模块可以根据定义的键来限制每个键值的连接数,如同一个IP来源的连接数。并不是所有的连接都会被该模块计数,只有那些正在被处理的请求(这些请求的头信息已被完全读入)所在的连接才会被计数。
    我们可以在nginx_conf的http{}中加上如下配置实现限制:

    #限制每个用户的并发连接数,取名one 
    limit_conn_zone $binary_remote_addr zone=one:10m;
    配置记录被限流后的日志级别,默认error级别
    limit_conn_log_level error;
    #配置被限流后返回的状态码,默认返回503
    limit_conn_status 503;	
    

    然后在server{}里加上如下代码:

    #限制用户并发连接数为1
    limit_conn one 1;
    

    然后我们是使用ab测试来模拟并发请求:
    ab -n 5 -c 5 http://10.23.22.239/index.html
    得到下面的结果,很明显并发被限制住了,超过阈值的都显示503

    另外刚才是配置针对单个IP的并发限制,还是可以针对域名进行并发限制,配置和客户端IP类似。

    #http{}段配置
    limit_conn_zone $ server_name zone=perserver:10m;
    #server{}段配置
    limit_conn perserver 1;	
    
  • ngx_http_limit_req_module
    上面我们使用到了ngx_http_limit_conn_module 模块,来限制连接数。那么请求数的限制该怎么做呢?这就需要通过ngx_http_limit_req_module 模块来实现,该模块可以通过定义的键值来限制请求处理的频率。特别的,可以限制来自单个IP地址的请求处理频率。 限制的方法是使用了漏斗算法,每秒固定处理请求数,推迟过多请求。如果请求的频率超过了限制域配置的值,请求处理会被延迟或被丢弃,所以所有的请求都是以定义的频率被处理的。
    在http{}中配置

    #区域名称为one,大小为10m,平均处理的请求频率不能超过每秒一次。
    limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
    

    在server{}中配置

    #设置每个IP桶的数量为5
    limit_req zone=one burst=5;
    

    上面设置定义了每个IP的请求处理只能限制在每秒1个。并且服务端可以为每个IP缓存5个请求,如果操作了5个请求,请求就会被丢弃。
    使用ab测试模拟客户端连续访问10次:ab -n 10 -c 10 http://10.23.22.239/index.html
    设置了桶的个数为5个。一共10个请求,第一个请求马上被处理。第2-6个被存放在桶中。由于桶满了,没有设置nodelay因此,余下的4个请求被丢弃。

  • openresty(nginx+lua)
    OpenResty实现限流的几种方式

spring cloud的zuul

Spring Cloud:服务网关 Zuul

  • Zuul 是开源的微服务网关,可与 Eureka、Ribbon、Hystrix 等组件配合使用,Zuul 它的核心是一系列过滤器,这些过滤器可完成下面功能:
    • 身份认证与安全:识别每个资源的验证要求,并拒绝那些要求不符合的请求
    • 审核与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图
    • 动态路由:动态的将请求路由到不同的后端集群
    • 压力测试:逐渐增加指向集群的流量,以了解性能
    • 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
    • 静态响应处理:在边缘位置直接建立部分响应,从而避免转发到内部集群
    • 多区域弹性:跨越 AWS Region 进行请求路由,实现 ELB 使用多样化,让系统边缘更贴近使用者
  • Spring Cloud 对 Zuul 进行了整合和增强,Zuul 默认使用的 HTTP 客户端是 Apache Http Client,也可使用 RestClient 或 okHttpClient

内容引用 Spring Cloud:服务网关 Zuul

spring cloud Hystrix

Hystrix 主要用于熔断降级

  • Hystrix的设计原则
    • 防止单个服务的故障耗尽整个服务的Servlet容器(如Tomcat)的线程池资源。
    • 快速失败机制,如果某个服务出现了故障,则调用该服务的请求快速失败,而不是线程等待。
    • 提供回退方案,在请求发生故障时,提供设定好的回退方案。
    • 使用熔断器机制,防止故障扩散到其他的服务。
    • 提供熔断器的监控组件Hystrix Dashboard,可以实时监控熔断器的状态。
  • Hystrix的工作机制
    • 当服务的某个API接口的失败次数在一定时间内小于设定的阈值时,熔断器处于关闭状态,该API接口正常提供服务。
    • 当该API接口处理请求的失败次数大于设定的阈值时,Hystrix判定该API接口出现了故障,打开熔断器,这时该API接口会执行快速失败的逻辑,不执行业务逻辑,请求的线程不会处于阻塞状态。
    • 处于打开状态的熔断器在一定时间后会处于半打开状态,并将一定数量的请求执行正常逻辑,剩余的请求会执行快速失败。
    • 若执行正常逻辑的请求失败了,则熔断器继续打开,若成功了,则熔断器关闭。这样熔断器就具有了自我修复的功能。

内容引用 熔断器Hystrix

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/zhaokuner/article/details/103355996

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签