唐山网站制作网络公司,黑帽seo软件,做网站对服务器要求,湖南常德今天最新消息Sentinel服务熔断和流控
简介
Sentinel
随着微服务的流行#xff0c;服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件#xff0c;主要以流量为切入点#xff0c;从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来…Sentinel服务熔断和流控
简介
Sentinel
随着微服务的流行服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件主要以流量为切入点从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 源码地址https://github.com/alibaba/Sentinel 官方文档https://github.com/alibaba/Sentinel/wiki
https://sentinelguard.io/zh-cn/docs/circuit-breaking.html
Spring Cloud Alibaba Sentinel 同时兼具了熔断器和流控的功能。
Sentinel具有以下特征: 丰富的应用场景 Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景例如秒杀即突发流量控 制在系统容量可以承受的范围、消息削峰填谷、实时熔断下游不可用应用等。 完备的实时监控 Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据甚至 500 台以下规模的集群的汇总运行情况。 广泛的开源生态 Sentinel 提供开箱即用的与其它开源框架/库的整合模块例如与 Spring Cloud、Dubbo、 gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。 完善的 SPI 扩展点 Sentinel 提供简单易用、完善的 SPI 扩展点。您可以通过实现扩展点快速的定制逻辑。例如定制规则管理、适配数据源等。 Spring的spi是通过ClassLoader去META-INF/spring.factories加载class然后反射实例化返回。像SpringBoot用这种方式去加载一些自动配置类即引入xx-starter就能够自动向spring容器中注入许多配置好的组件。
阿里云提供了 企业级的 Sentinel 服务应用高可用服务 AHAS Sentinel和Hystrix对比
https://github.com/alibaba/Sentinel/wiki/Sentinel-%E4%B8%8E-Hystrix-%E7%9A%84%E5%AF%B9%E6%AF%94
SentinelHystrix隔离策略信号量隔离线程池隔离/信号量隔离熔断降级策略基于响应时间或失败比率基于失败比率实时指标实现滑动窗口滑动窗口基于 RxJava规则配置支持多种数据源支持多种数据源扩展性多个扩展点插件的形式基于注解的支持支持支持限流基于 QPS支持基于调用关系的限流有限的支持流量整形支持慢启动、匀速器模式不支持系统负载保护支持不支持控制台开箱即用可配置规则、查看秒级监控、机器发现等不完善常见框架的适配Servlet、Spring Cloud、Dubbo、gRPC 等Servlet、Spring Cloud Netflix
熔断
微服务架构的系统通常会包含多个微服务各个微服务可能部署在不同的机器上并通过网络进行通信那么就不可避免会遇到 “网络请求超时” 、“微服务不可用” 等问题这就会进一步引起依赖它的微服务不可用这样不断引发服务故障的现象称为『雪崩效应』最终的结果是整个应用系统瘫痪。
为了解决上述问题编程领域参考现实生活提出了熔断器 使用熔断器模式如果请求出现异常所有请求都会直接返回而不会等待或阻塞这样可以减少资源的浪费。 熔断器所造成的这种现象也叫『快速失败fast fall』。
流控
限流功能指的是 Sentinel类似于过滤器、拦截器的效果在收到请求后拒绝请求的放行至 Controller而是直接返回从而减少对 Controller乃至 Service 的触发执行。 熔断和限流的区别在于熔断是确确实实发生了错误而限流是人为根据设置强行让一部分请求被打回。 sentinel安装
sentinel-dashboard 的下载安装
sentinel-dashboard 是基于 Spring Boot 开发的控制台。打包后可以直接运行不需要额外的 Tomcat 等应用容器。Sentinel 控制台不仅能展示服务流控、熔断降级相关的数据还可以通过配置的方式动态的为 Sentinel 客户端下发流量控制的指令
我们需要下载并安装的是 sentinel-dashBoard 下载地址https://github.com/alibaba/Sentinel/releases 注意启动 sentinel-dashboard 需要 JDK 版本为 1.8 及以上版本。 使用如下命令启动控制台
java -Dserver.port8840 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.1.jar-Dserver.port8840 用于指定 Sentinel 控制台端口为 8840。默认是 8080 。 -Dproject.namesentinel-dashboard 指定 Sentinel 控制台程序的名称。 说明 如果你有多张网卡的话你还需要指定使用哪张网卡IP来接受各个微服务上报的信息
-Dcsp.sentinel.heartbeat.client.ip192.168.xxx.xxx访问网址[http://127.0.0.1:8840]
从 1.6.0 起sentinel-dashboard 引入基本的登录功能默认用户名和密码都是 sentinel 。当然也可以通过 JVM 参数的方式进行修改 -Dsentinel.dashboard.auth.usernamesentinel 用于指定控制台的登录用户名为 sentinel -Dsentinel.dashboard.auth.password123456 用于指定控制台的登录密码为 123456如果省略这两个参数默认用户和密码均为 sentinel -Dserver.servlet.session.timeout7200 用于指定 Spring Boot 服务端 session 的过期时间如 7200 表示 7200 秒60m 表示 60 分钟默认为 30 分钟
Sentinel 本身就是一个 Spring Boot 应用所以jar 包内部的 application.properties 文件也是可以修改配置的。
Sentinel实现限流
Spring Cloud Alibaba Sentinel 可以分别用在服务的 “请求发起方” 和 “请求被调方”
请求发起方使用的是 OpenFeign 因此这种情况下 Sentinel 是和 OpenFeign 进行整合请求被调用使用的是 Spring MVC因此这种情况下 Sentinel 是和 Spring MVC 进行整合
同时又由于 Sentinel 兼具熔断和流控两个功能因此这里就有 4 种情况
在服务发起方项目中整合 OpenFeign 进行实现熔断功能在服务发起方项目中整合 OpenFeign 进行实现限流功能在服务被调方项目中整合 Spring MVC 进行实现熔断功能在服务被调方项目中整合 Spring MVC 进行实现限流功能。
这样以来功能上就出现了重叠冗余因此在实际使用中我们是这样安排的
在服务发起方Sentinel 整合 OpenFeign 实现熔断功能在服务被调方Sentinel 整合 Spring MVC 实现限流功能。
总结流控针对provider熔断降级针对consumer
sentinel实现限流
回顾前面笔记中的 “关于 Sentinel 的使用方式” 章节在这里我们在服务的 “被调方” 使用 Sentinel 整合 Spring MVC 进行流量控制。 在这里Sentinel 借助 Spring MVC 框架的 “拦截器” 机制整合进入 Spring MVC “抢先” 在 Controller 执行之前进行流控和熔断的判断从而决定当前请求是否被放行至 Controller
sentinel整合mvc
1.引入相关依赖
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId
/dependency
!-- 其实真正起作用的是被关联引入的 sentinel-spring-webmvc-adapter 包 --2.添加配置连接到 sentinel-dashboard
spring:cloud:sentinel:transport:dashboard: 127.0.0.1:8080port: 8719feign:sentinel:enabled: true3.访问 sentinel-dashboard
只需要完成上述的配置代码不需要有任何的调整我们就可以通过实时监控查看服务内的流量 QPS每秒查询率 以及平均响应时长等信息。 只有服务接口被访问的情况下在 sentinel 里面才可以看到监控信息。这可能会让你『等』一段时间。 相关概念
上下文 Context 和 context-name
Context 代表调用链路上下文。是一个根节点在整个调用链路的开始处Sentinel 会创建上下文 Context 对象并且为它指定一个 name 相当于根资源。在 Sentinel 中不同的调用链路可能使用同一个上下文 Context 对象共一个根节点。在这里 和 Spring MVC 整合 我们的调用链路都是在 sentinel_spring_web_context 中 资源Resource和 resource-name
在 Sentinel 中对于每一份资源Sentinel 会为赋予一个 name或者你手动指定,和 Spring MVC 整合时Sentinel 使用的是 URI 来作为 Controller 方法的资源名 在这里Controller 方法就是资源 流控规则
在菜单左侧的 簇点链路和流控规则都可以针对 服务接口添加流控规则
当我们的服务接口资源被访问的时候就会出现在 簇点链路 列表中我们可以针对该服务接口资源配置流程控制规则 说明 资源名表示我们针对哪个接口资源进行流控规则配置如/test2/{id} 针对来源表示针对哪一个服务访问当前接口资源的时候进行限流default 表示不区分访问来源。如填写服务名称xxx-service表示 xxx-service 访问前接口资源的时候进行限流其他服务访问该接口资源的时候不限流一般就是默认为default即可。 阈值类型/单机阈值QPS每秒钟请求数量。上图配置表示每秒钟超过2次请求的时候进行限流当然我们可以设置线程数表示开启 n 个线程处理资源请求这个不是只每秒2个线程对服务端 /test1请求资源接口的 2 个线程都被占用的时候其他访问失败一般用的都是QPS 是否集群默认情况下我们的限流策略都是针对单个服务的当然sentinel 提供了集群限流的功能。 除非你的微服务规模特别大一般不要使用集群模式。集群模式需要各节点与 token server 交互才可以会增加网络交互次数一定程度上会拖慢你的服务响应时间。 上面的限流规则用一句话说对于任何来源的请求当超过每秒 2 次的标准之后就直接限流访问失败抛出 BlockException 异常 流控规则高级选项
1.流控模式
直接当前资源达到限流标准时就直接限流默认值关联/important接口的重要程度要高于 /normal接口如果/important接口的访问压力很大那么可以『牺牲』掉 /normal 接口全力保证 /important 接口的正常运行
例如我们在resttemplate-a微服务中创建两个接口
GetMapping(/query)
public String query(){return ok:query;
}GetMapping(/add)
public String add(){return ok:add;
}先访问http://localhost:9527/add和http://localhost:9527/query 我们对/query接口进行限流这个配置的意思就是当每秒对/add接口的请求超过2次时就对/query接口进行限流要注意这样是优先保证/add不限流牺牲的是/query接口。10s内对/add接口超过20次请求那么就对/query接口限流
测试 链路
链路限流和关联限流的思路很像假设我们要去请求某个微服务该微服务有2个接口/query和/add而这两个接口又调用了同一个service层的方法(如doSomething方法)那么我们可以『站在 doSomething的方法』的角度上进行设置如果是 /query接口在调用service层的 doSomething方法那么就进行限流而 /add接口的调用就不限流或设置为更宽松一些的流控
1.配置设置通过配置关闭 sentinel 的 URL 收敛功能
spring:application:name: resttemplate-acloud:nacos:discovery:server-addr: localhost:8848sentinel:transport:dashboard: localhost:8840web-context-unify: false #默认是开启上下文整合所有链路在根节点下链路监控就是将请求分开统计2.代码设计
controller层
GetMapping(/query)
public String query(){return userService.doSomething();
}
GetMapping(/add)
public String add(){return userService.doSomething();
}
//service层
Component
public class UserService {SentinelResource(doSomething)public String doSomething() {return hello world;}
}3.重新运行先在界面发送请求 http://localhost:9527/query和http://localhost:9527/add然后sentinel配置 链路配置 4.测试在jmeter对/add测试时不限流如10秒钟对/add请求80次但是同时在浏览器对/query测试时每秒只能是2次请求。
2.流控效果
快速失败很简单的说就是达到限流标准后请求就被拦截直接失败。HTTP状态码429 too many request默认值Warm up预热模式也有叫冷启动主要是为系统启动时设置预热时间底层有预热因子是3在系统刚启动时使用的阈值不再是每秒多少个请求而是设置的阈值除以预热因子在预热的时间内逐渐提升阈值最后达到设置的阈值也就是每秒多少个请求好处是预防系统刚启动时突发大量的请求服务容易宕机。
1.代码设计
GetMapping(/test/{id})
public ResponseEntityString test1(PathVariable Integer id){return new ResponseEntity(ok, HttpStatus.OK);
}2.配置设置 在10秒内每秒允许的请求数会逐渐增加也就是每秒的阈值逐渐提高
3.测试 排队等待也叫流量整形它让请求以均匀的速度通过单机阈值为每秒通过数量其余的在队列排队等待一段时间即我们设置的时间单位是毫秒没有超过这个时间都能被及时处理如果超过了这个等待时间针对请求的接口没有线程来处理则抛出异常 测试每秒50个请求 Sentinel 和 SpringMVC 整合原理
Sentinel 和 Spring MVC 的整合利用了 Spring MVC 的拦截器机制Sentinel 实现了一个名为 SentinelWebInterceptor 的拦截器其逻辑伪代码如下
public SentinelWebInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){try {1. 初始化上下文;2. 熔断、流控逻辑的判断判断当前请求是否能继续执行;return true; // 此时 Controller 方法会被调用。Controller 方法就是 3 。} catch (BlockException e) {4. 上述第 2 步未能通过会抛出 BlockException 表示请求被拒绝return false;}}public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, Nullable ModelAndView modelAndView) throws Exception {} public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Nullable Exception ex) throws Exception {if (发生了异常) {5. 业务异常。记录、统计异常信息}6. 收尾工作曾经创建的资源该回收的回收该清除的清除}自定义限流异常信息返回
Sentinel 返回的默认信息是 Blocked by Sentinel (flow limiting)如果你对默认响应信息不满意你可以自定义限流返回信息。
Sentinel 提供了 BlockExceptionHandler 接口。不管什么原因触发了 Sentinel 阻断用户的正常请求Sentinel 都将『进入』到用户自定义的 BlockExceptionHandler 接口的实现类中执行 handle 方法并传入当前的请求、响应对象以及异常对象并以 handle 方法的执行结果作为返回回传给用户。
Component
public class MyBlockExceptionHandler implements BlockExceptionHandler {Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws Exception {String msg null;if (ex instanceof FlowException) {msg 该请求限流了请稍后重试;} else if (ex instanceof DegradeException) {msg 被熔断了;} else {msg 其它原因;// ParamFlowException 热点参数限流;// SystemBlockException 系统规则负载/...不满足要求;// AuthorityException 授权规则不通过;}// http 状态码response.setStatus(500);response.setCharacterEncoding(utf-8);response.setHeader(Content-Type, application/json;charsetutf-8);response.setContentType(application/json;charsetutf-8);new ObjectMapper().writeValue(response.getWriter(), msg);}
}需要说明的是不仅仅是因为限流和熔断这一个原因会导致 BlockExceptionhandler 的 handle 方法的执行还有其它的原因也会调用这个handler方法因此需要对 handle 方法的 BlockException 参数对象进行 instanceof 判断 sentinel服务熔断降级
我们在服务的 “请求发起方” 使用 Sentinel 整合 OpenFeign 进行熔断降级
sentinel整合feign
1.添加依赖
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-sentinel/artifactId
/dependency
dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId
/dependency
dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId
/dependency2.添加配置连接到 sentinel-dashboard
spring:cloud:sentinel:transport:dashboard: 127.0.0.1:8840
feign:sentinel:enabled: true ##启用 Sentinel 与 OpenFeign 整合适配器3.代码实现spring-service-a-feign微服务调用spring-service-b微服务
FeignClient(value spring-service-b,qualifier feignclient,fallback PermFeignClientImpl.class )
public interface PermFeignClient {GetMapping(/perms/{id})public Perms getPermsById(PathVariable(id) Integer id);
}
降级代码
Component
public class PermFeignClientImpl implements PermFeignClient {Overridepublic Perms getPermsById(Integer id) {Perms perms new Perms();perms.setName(服务器忙请稍后再试);return perms;}
}
controller
RestController
public class PermController {Autowired Qualifier(feignclient)private PermFeignClient permFeignClient;GetMapping(/perm)public Perms getPermsById(Integer id) {Perms perms permFeignClient.getPermsById(id);return perms;}
}spring-service-b微服务
GetMapping(/perms/{id})
public Perms getPermsById(PathVariable(id) Integer id) {if(id1){try {Thread.sleep(800); //当id为1时800毫秒才有相应}catch (Exception ex){ }}if(id2){throw new RuntimeException();}return permService.getPermsById(id);
}4.熔断规则
在 sentinel-dashboard 上你可以看到有 降级规则它指的就是『设置当满足什么条件时对服务进行降级』 慢调用比例
如下配置在一秒内发5次请求如果每次请求的响应时间超过500毫秒这种比例达到0.550%就进行熔断熔断时长就是10秒。如1秒内有5次请求其中有3次请求响应时间超过了500毫秒那么这个比例就是60%大于50%此时就熔断然后降级。 用jmeter测试程序中当id1时每次响应都是800毫秒。所以每次的请求都大于500毫秒失败率100%这个时候去请求id4的资源也是无法请求的因为熔断了所以也是直接降级。10s后再次请求id4的就正常了。
异常数
如下配置一秒内发送5次请求如果有3次失败异常则直接熔断然后降级 测试localhost:9527/perm?id2结果5次都失败了此时熔断时长是9秒在这9秒内如果去请求id4的依然是降级9s之后试着去发送id4的请求如果通过则进入闭合正常状态。
异常比例
如下配置1秒钟发送5次请求如果调用接口最终失败的比例超过了20%则熔断9s。 #配置
spring:cloud:sentinel:eager: true #取消Sentinel控制台懒加载blockhandler fallback,blockhandler 优先级高 }catch (Exception ex){ }
}
if(id2){throw new RuntimeException();
}
return permService.getPermsById(id);}
4.熔断规则在 sentinel-dashboard 上你可以看到有 降级规则它指的就是『**设置当满足什么条件时对服务进行降级**』[外链图片转存中...(img-QwfGPW1A-1694490781354)]#### 慢调用比例如下配置在一秒内发5次请求如果每次请求的响应时间超过500毫秒这种比例达到0.550%就进行熔断熔断时长就是10秒。如1秒内有5次请求其中有3次请求响应时间超过了500毫秒那么这个比例就是60%大于50%此时就熔断然后降级。[外链图片转存中...(img-d74m5bKk-1694490781357)] 用jmeter测试程序中当id1时每次响应都是800毫秒。所以每次的请求都大于500毫秒失败率100%这个时候去请求id4的资源也是无法请求的因为熔断了所以也是直接降级。10s后再次请求id4的就正常了。#### 异常数如下配置一秒内发送5次请求如果有3次失败异常则直接熔断然后降级[外链图片转存中...(img-URgCSfH7-1694490781358)] 测试localhost:9527/perm?id2结果5次都失败了此时熔断时长是9秒在这9秒内如果去请求id4的依然是降级9s之后试着去发送id4的请求如果通过则进入闭合正常状态。#### 异常比例如下配置1秒钟发送5次请求如果调用接口最终失败的比例超过了20%则熔断9s。[外链图片转存中...(img-bYCdjt00-1694490781358)] yaml
#配置
spring:cloud:sentinel:eager: true #取消Sentinel控制台懒加载
blockhandler fallback,blockhandler 优先级高