原文:https://blog.vchar.top/java/1615900200.html
微服务中为了防止某个服务出现问题,导致影响整个服务集群无法提供服务的情况,我们在系统访问量和业务量高起来了后非常有必要对服务进行熔断限流处理。 其中熔断即服务发生异常时能够更好的处理;限流是限制每个服务的资源(比如说访问量)。
spring-cloud中很多使用的是Hystrix组件来进行限流的,现在我们这里使用阿里的sentinel来实现熔断限流功能。
sentinel简介
这个在阿里云有企业级的商用版本 应用高可用服务 AHAS;现在有免费的入门级可以先体验下,之后再决定是否使用付费的专业版或者是自己搭建。
sentinel功能概述
- 流量控制:将随机的请求调整为合适的形状。即限制请求数量;
- 熔断降级:当检测到调用链路中某个资源出现不稳定的表现,如请求响应时间长或者异常比例升高的时候,则对此资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。 采用的手段:1.并发线程数的限制;2.通过响应时间进行降级
- 系统负载保护:Sentinel提供系统维度的自适应保护能力。即在系统负载较高时,自动将流量转发到其它集群中的机器上去, 使系统的入口流量和系统的负载达到一个平衡,保护系统能力范围内处理最多的请求。
sentinel和Hystrix的区别
- 两者的原则是一致的,都是当一个资源出现问题时,让其快速失败,不波及到其它服务。
- Hystrix采用的是线程池隔离的方式,优点是做到了资源之间的隔离,缺点是增加了线程切换的成本
- Sentinel采用的是通过并发线程的数量和响应时间来对资源限制。
Sentinel规则
Sentinel默认定义如下规则:
流控规则
通过QPS或并发线程数来做限制,里面的针对来源可以对某个微服务做限制,默认是都限制。
- 流控模式:
- 直接:接口达到限流条件,开启限流;
- 关联:当关联的资源达到限流条件时,开启限流(适合做应用让步)
- 链路:当从某个接口过来的资源达到限流条件时,开启限流(限制更细致)
关于配置规则:可以直接使用url地址来配置,也可以通过自定义名称来配置(需要在方法上添加@SentinelResource("order")
注解才能达到效果,可以重复)
链路限流不生效的问题:由于sentinel基于filter开发的拦截使用的链路收敛的模式,因此需要设置关闭链路收敛使链路收敛能够生效,
spring:
cloud:
sentinel:
filter:
# 关闭链路收敛使链路收敛能够生效
enabled: false
降级规则
当满足设置的条件,对服务进行降级。
- 根据平均响应时间:当资源的平均响应时间超过阀值(以ms为单位)之后,资源进入准降级状态。如果接下来1秒持续进入的n个请求的RT都持续超过这个阀值,则在接下来的时间窗口(单位s)之内就会使这个方法进行服务降级。
注意Sentinel默认的最大时间为4900ms,超过这个时间将被默认设置为4900ms;可以通过启动配置 -Dcsp.sentinel.statistic.max.rt=xxx来修改。
- 异常降级:通过设置异常数或者异常比例来进行服务降级。
热点规则
必须使用@SentinelResource("order")
注解来做标记,将限流做到参数级别上去,并且可以配置排除参数值等于某个值时不做限流。
授权规则
通过配置黑白名单来设置是否允许通过。
自定义来源获取规则:
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
/**
* <p> sentinel自定义授权来源获取规则 </p>
*/
@Component
public class RequestOriginParserDefinition implements RequestOriginParser {
/**
* 定义区分来源的规则:本质上是通过获取request域中获取来源标识,然后交给流控应用来进行匹配处理
*
* @param request request域
* @return 返回区分来源的值
*/
@Override
public String parseOrigin(HttpServletRequest request) {
String client = request.getHeader("client");
if(StringUtils.isNotBlank(client)){
return "NONE";
}
return client;
}
}
系统规则
系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体Load、RT、入口QPS、CPU使用率和线程数五个维度来监控整个应用数据,让系统跑到最大吞吐量的同时保证系统稳定性。
- Load(仅对 Linux/Unix-like 机器生效):当系统 load1 超过阈值,且系统当前的并发线程数超过系统容量时才会触发系统保护。系统容量由系统的 maxQps * minRt 计算得出。设定参考值一般是 CPU cores * 2.5。
- RT:当单台机器上所有入口流量的平均 RT 达到阈值即触发系统保护,单位是毫秒。
- 线程数:当单台机器上所有入口流量的并发线程数达到阈值即触发系统保护。
- 入口 QPS:当单台机器上所有入口流量的 QPS 达到阈值即触发系统保护。
- CPU使用率:当单台机器上所有入口流量的 CPU使用率达到阈值即触发系统保护。
sentinel的使用
下面我们通过一些简单的示例来快速了解sentinel的使用。
安装控制台界面工具
在Sentinel的Github上下载安装包https://github.com/alibaba/Sentinel/releases;就是一个jar包直接使用命令启动即可。
java -Dserver.port=9080 -Dcsp.sentinel.dashboard.server=localhost:9080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
-Dserver.port
是设置访问的端口号;
sentinel-dashboard.jar 就是刚刚下载的jar包名称;
为方便使用可以创建一个bat启动文件,在里面输入上面的命令行,后面启动直接点击这个bat文件即可。
从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel;启动成功后浏览器输入http://127.0.0.1:9080 即可访问控制台。注意这个控制台不是必须接入的,同时只有你的接口方法被访问过后控制台里面才会显示。
服务中使用
添加如下依赖包
<!--由于我们使用的spring-cloud,因此这里因此 sentinel的集成包来简化我们的配置 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--sentinel 对dubbo的支持-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
</dependency>
</