SpringCloud系列——限流、熔断、降级
前言
分布式环境下,服务直接相互调用,一个复杂的业务可能要调用多个服务,例如A -> B -> C -> D,当某个服务出现异常(调用超时、调用失败等)将导致整个流程阻塞崩溃,严重的整个系统都会崩掉,为了实现高可用,必要的保护机制必不可少
本文记录限流、熔断、降级的实现处理
限流
我们采用令牌桶限流法,并自己实现一个简单令牌桶限流
有个任务线程以恒定速率向令牌桶添加令牌
一个请求会消耗一个令牌,令牌桶里的令牌大于0,才会放行,反正不允许通过
- /**
- * 简单的令牌桶限流
- */
- public class RateLimiter {
- /**
- * 桶的大小
- */
- private Integer limit;
- /**
- * 桶当前的token
- */
- private static Integer tokens = 0;
- /**
- * 构造参数
- */
- public RateLimiter(Integer limit, Integer speed){
- //初始化桶的大小,且桶一开始是满的
- this.limit = limit;
- tokens = this.limit;
- //任务线程:每秒新增speed个令牌
- new Thread(() ->{
- while (true){
- try {
- Thread.sleep(1000L);
- int newTokens = tokens + speed;
- if(newTokens > limit){
- tokens = limit;
- System.out.println("令牌桶满了!!!");
- }else{
- tokens = newTokens;
- }
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- /**
- * 根据令牌数判断是否允许执行,需要加锁
- */
- public synchronized boolean execute() {
- if (tokens > 0) {
- tokens = tokens - 1;
- return true;
- }
- return false;
- }
- }
main简单测试
- public static void main(String[] args) {
- //令牌桶限流:峰值每秒可以处理10个请求,正常每秒可以处理3个请求
- RateLimiter rateLimiter = new RateLimiter(10, 3);
- //模拟请求
- while (true){
- //在控制台输入一个值按回车,相对于发起一次请求
- Scanner scanner = new Scanner(System.in);
- scanner.next();
- //令牌桶返回true或者false
- if(rateLimiter.execute()){
- System.out.println("允许访问");
- }else{
- System.err.println("禁止访问");
- }
- }
- }
在SpringCloud分布式下实现限流,需要把令牌桶的维护放到一个公共的地方,比如Zuul路由,当然也可以同时针对具体的每个服务进行单独限流
另外,guava里有现成的基于令牌桶的限流实现,引入
- <dependency>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- <version>26.0-jre</version>
- </dependency>
具体用法这里就不阐述了
我们找出之前的springcloud项目,在zuul-server中的AccessFilter过滤器进行限流,其他的都不变,只需要做如下修改
PS:我这里为了方便测试,调小了令牌桶的大小,跟速率,正常情况下要服务器的承受能力来定
- /**
- * Zuul过滤器,实现了路由检查
- */
- public class AccessFilter extends ZuulFilter {
- //令牌桶限流:峰值每秒可以处理10个请求,正常每秒可以处理3个请求
//PS:我这里为了方便测试,调小了令牌桶的大小,跟速率,正常情况下按服务器的承受能力来定- private RateLimiter rateLimiter = new RateLimiter(2, 1);
- //业务不变,省略其他代码...
- /**
- * 过滤器的具体逻辑
- */
- @Override
- public Object run() {
- RequestContext ctx = RequestContext.getCurrentContext();
- HttpServletRequest request = ctx.getRequest();
- HttpServletResponse response = ctx.getResponse();
- //限流
- if(!rateLimiter.execute()){
- try {
- ctx.setSendZuulResponse(false);
- ctx.setResponseStatusCode(200);
- //直接写入浏览器
- response.setContentType("text/html;charset=UTF-8");
- PrintWriter writer = response.getWriter();
- writer.println("系统繁忙,请稍后在试!<br/>System busy, please try again later!");
- writer.flush();return null;
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- //业务不变,省略其他代码..
- }
- }
按照我们设置的值,一秒能处理一个请求,峰值一秒能处理两个请求,下面疯狂刷新进行测试
熔断
yml配置开启Hystrix熔断功能,进行容错处理
- feign:
- hystrix:
- enabled: true
设置Hystrix的time-out时间
- hystrix:
- command:
- default:
- execution:
- isolation:
- thread:
- timeoutInMilliseconds: 5000 #毫秒
- #或者设置从不超时
- #timeout:
- # enabled: false
在使用Feign调用服务提供者时配置@FeignClient的 fallback,进行容错处理(服务提供者发生异常),如果需要获取到异常信息,则要配置fallbackFactory<T>
- @FeignClient(name = "sso-server", path = "/",/*fallback = SsoFeign.SsoFeignFallback.class,*/fallbackFactory = SsoFeign.SsoFeignFallbackFactory.class)
- /**
- * 容错处理(服务提供者发生异常,将会进入这里)
- */
- @Component
- public class SsoFeignFallback implements SsoFeign {
- @Override
- public Boolean hasKey(String key) {
- System.out.println("调用sso-server失败,进行SsoFeignFallback.hasKey处理:return false;");
- return false;
- }
- }
- /**
- * 只打印异常,容错处理仍交给 SsoFeignFallback
- */
- @Component
- public class SsoFeignFallbackFactory implements FallbackFactory<SsoFeign> {
- private final SsoFeignFallback ssoFeignFallback;
- public SsoFeignFallbackFactory(SsoFeignFallback ssoFeignFallback) {
- this.ssoFeignFallback = ssoFeignFallback;
- }
- @Override
- public SsoFeign create(Throwable cause) {
- cause.printStackTrace();
- return ssoFeignFallback;
- }
- }
FallbackFactory也可以这样写
- /**
- * 容错处理
- */
@Component
public class SsoFeignFallbackFactory implements FallbackFactory<SsoFeign> {- @Override
- public SsoFeign create(Throwable cause) {
- //打印异常
- cause.printStackTrace();
- return new SsoFeign() {
- @Override
- public Boolean hasKey(String key) {
- System.out.println("调用sso-server失败:return false;");
- return false;
- }
- };
- }
- }
因为我们没有启动Redis,报错,但我们进行容错处理,所以还是返回了false
降级
当调用服务发送异常,容错处理的方式有多种,我们可以:
1、重连,比如服务进行了限流,本次连接被限制,重连一次或N次就可以得到数据
2、直接返回一个友好提示
3、降级调用备用服务、返回缓存的数据等
后记
降级也可以叫做“备胎计划”...
代码开源
代码已经开源、托管到我的GitHub、码云:
GitHub:https://github.com/huanzi-qch/springCloud
码云:https://gitee.com/huanzi-qch/springCloud
SpringCloud系列——限流、熔断、降级的更多相关文章
- springBoot整合Sentinel实现降级限流熔断
由于hystrix的停止更新,以及阿里Sentinel在历年双十一的贡献.项目中使用了Sentinel,今天我们来讲讲Sentinel的入门教程,本文使用1.6.3版本进行讲解 本文通过Sentine ...
- Hystrix介绍以及服务的降级限流熔断
(dubbo熔断,Hystrix问的少) 无论是缓存层还是存储层都会有出错的概率,可以将它们视同为资源.作为并发量较大的系统,假如有一个资源不可用,可能会造成线程全部 hang (挂起)在这个资源上, ...
- 高可用服务设计之二:Rate limiting 限流与降级
<高可用服务设计之二:Rate limiting 限流与降级> <nginx限制请求之一:(ngx_http_limit_conn_module)模块> <nginx限制 ...
- .net core使用ocelot---第四篇 限流熔断
简介 .net core使用ocelot---第一篇 简单使用 .net core使用ocelot---第二篇 身份验证 .net core使用ocelot---第三篇 日志记录 前几篇文章我们陆续介 ...
- 0.9.0.RELEASE版本的spring cloud alibaba sentinel限流、降级处理实例
先看服务提供方的,我们在原来的sentinel实例(参见0.9.0.RELEASE版本的spring cloud alibaba sentinel实例)上加上限流.降级处理,三板斧只需在最后那一斧co ...
- .Net微服务实践(四)[网关]:Ocelot限流熔断、缓存以及负载均衡
目录 限流 熔断 缓存 Header转化 HTTP方法转换 负载均衡 注入/重写中间件 后台管理 最后 在上篇.Net微服务实践(三)[网关]:Ocelot配置路由和请求聚合中我们介绍了Ocelot的 ...
- DBPack 限流熔断功能发布说明
上周我们发布了 v0.4.0 版本,增加了限流熔断功能,现对这两个功能做如下说明. 限流 DBPack 限流熔断功能通过 filter 实现.要设置限流规则,首先要定义 RateLimitFilter ...
- Dubbo学习系列之十(Sentinel之限流与降级)
各位看官,先提个问题,如果让你设计一套秒杀系统,核心要点是啥???我认为有三点:缓存.限流和分离.想当年12306大面积崩溃,还有如今的微博整体宕机情况,感觉就是限流降级没做好,"用有限的资 ...
- SpringCloud微服务:Sentinel哨兵组件,管理服务限流和降级
源码地址:GitHub·点这里||GitEE·点这里 一.基本简介 1.概念描述 Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性.包括核心的独立类库,监 ...
随机推荐
- 多线程——继承Thread类别
详细java此前使用多线程,让我们来看看下面的问题. 什么是多线程 简单的理解成:cpu"同一时候"运行多个任务,这就是多线程. (究其本质,当涉及到进程和线程的概念.上面 ...
- 关于WPF你应该知道的2000件事
原文 关于WPF你应该知道的2000件事 以下列出了迄今为止为WPF博客所知的2,000件事所创建的所有帖子. 帖子总数= 1,201 动画 #7 - 基于属性的动画 #686 - 使用动画制作图像脉 ...
- WPF - 模板查看工具:Show Me The Template及如何查看第三方主题
原文:WPF - 模板查看工具:Show Me The Template及如何查看第三方主题 在学习WPF的模板(DataTemplate.ItemsPanelTemplate.ControlTemp ...
- DirectX 图形流水线
Direct3D 的可编程流水线用来为实时游戏渲染图形(一个词概括——实时渲染) 上面的图是Dx11的实时渲染流水线,Dx的几个版本都是向下兼容的. Input-Assembler Stage: 输入 ...
- ASP Get请求
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- C# 异步委托的使用
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threa ...
- CSS,让100%的宽度,自动减10,让100%的高度,自动减10,可以加减乘除
CSS,让100%的宽度,自动减10,让100%的高度,自动减10,可以加减乘除 实例: .add{ width: calc(100% - 10px); height: calc(100% - 10p ...
- dotnetspider
http://www.cnblogs.com/modestmt/p/5525467.html nuget :DotnetSpider2.Core
- layabox pc app web同步发布的工具
http://layabox.com/ 或者vs + unity3d开发游戏
- 零元学Expression Blend 4 - Chapter 24 以实作了解Cover Flow功能
原文:零元学Expression Blend 4 - Chapter 24 以实作了解Cover Flow功能 今天要介绍一个Silverlight Toolkit内好用且在图片展示操作上很常见的元件 ...