Sentinel 是什么?
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应过载保护、热点流量防护等多个维度保护服务的稳定性。
官网:https://sentinelguard.io/zh-cn/index.html
项目介绍:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。
Hystrix 通过线程池的方式,来对依赖(在我们的概念中对应资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本,还需要预先给各个资源做线程池大小的分配。
Sentinel 对这个问题采取了两种手段:
- 通过并发线程数进行限制
和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。 - 通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
线程池隔离时候耗时长的请求,保证大量tomcat线程可用
线程池隔离和信号量隔离区别可以看看文章:Hystrix线程池隔离和信号量隔离的区别
下面简单实践下sentinel的使用吧:
一、 安装Jmeter
下载地址:http://jmeter.apache.org/download_jmeter.cgi
教程参考:JAVA常用工具--JMeter压力测试工具_lanyh996的博客-CSDN博客_java压力测试工具
二、 安装Sentinel
下载地址:https://github.com/alibaba/Sentinel/releases
下载的是jar包可以直接运行
java -Dserver.port=8480 -Dcsp.sentinel.dashboard.server=localhost:8480 -Dproject.name=sentinel-dashboard -Dsentinel.dashboard.auth.username=sentinel -Dsentinel.dashboard.auth.password=123456 -jar sentinel-dashboard-1.7.2.jar
参数说明:(注意:参数要放到 -jar的前边)
-Dserver.port=8480 # 指定控制台的端口为8480
-Dcsp.sentinel.dashboard.server=localhost:8480 # 指定要被哪个控制台监控(这里指定的是自己监控自己)
-Dproject.name=sentinel-dashboard # 指定实例名称(名称会在控制台左侧以菜单显示)
-Dsentinel.dashboard.auth.username=sentinel # 设置登录的帐号为:sentinel
-Dsentinel.dashboard.auth.password=123456 # 设置登录的密码为:123456
重启后访问:http://localhost:8480/
更多的参数参考:
启动配置:https://github.com/alibaba/Sentinel/wiki/%E5%90%AF%E5%8A%A8%E9%85%8D%E7%BD%AE%E9%A1%B9
登录鉴权:https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0#%E9%89%B4%E6%9D%83
SpringCloud项目服务端配置:
server:
port: 8321
spring:
application:
name: alibaba-sentinel # 项目名称,如果不写Sentinel会自己产生一个有端口号的名称
cloud:
sentinel:
transport:
# 端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互
port: 8719
# sentinel控制台地址
dashboard: localhost:8480
spring.cloud.sentinel.transport.port 端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了一个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。默认值8719
在接口中使用@SentinelResource注解
@GetMapping("/rateLimit/byURL")
@SentinelResource(value = "byURL")
public CommonGenericResultRes byURL(){
int i=0;
return new CommonGenericResultRes("按url限流测试ok");
}
启动后要先访问下该接口,才能在图形化界面看到
接下来对资源做下限流
启动Jmeter发送请求,可以看到简单的曲线波动
官网@SentinelResource的使用:注解支持 · alibaba/Sentinel Wiki (github.com)
@SentinelResource的参数如下:
value:资源名称
entryType:entry 类型,可选项(默认为 EntryType.OUT),可选EntryType.OUT和EntryType.IN
blockHandler/ blockHandlerClass:定位对应处理 BlockException 的函数名称blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockException。
fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。
defaultFallback(since 1.6.0):默认的 fallback 函数名称,可选项
exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
示例:
public class TestService {
// 原函数
@SentinelResource(value = "hello", blockHandler = "exceptionHandler", fallback = "helloFallback")
public String hello(long s) {
return String.format("Hello at %d", s);
}
// Fallback 函数,函数签名与原函数一致或加一个 Throwable 类型的参数.
public String helloFallback(long s) {
return String.format("Halooooo %d", s);
}
// Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
public String exceptionHandler(long s, BlockException ex) {
// Do some log here.
ex.printStackTrace();
return "Oops, error occurred at " + s;
}
// 这里单独演示 blockHandlerClass 的配置.
// 对应的 `handleException` 函数需要位于 `ExceptionUtil` 类中,并且必须为 public static 函数.
@SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class})
public void test() {
System.out.println("Test");
}
}
Sentinel一个比较显著的问题:就是随着项目的重启,原来做好的配置就都没有了,还需要再配置。这点如果是在生产环境是不能发生的。我们可以通过配置apollo避免这个问题。
添加依赖:
<!-- sentinel整合apollo进行规则持久化 -->
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
</dependency>
添加与 sentinel 规则相关的配置项:
# 项目名
spring.application.name = myApplication
# sentinel + apollo 进行规则持久化,为了方便管理,统一将所有项目的 sentinel 规则存放在 sentinel-rules 的公共NameSpace中
sentinel.datasource.rules.apollo.namespace-name = EDU001.sentinel-rules
# 规则类型:限流
spring.cloud.sentinel.datasource.flow.apollo.ruleType = flow
# 从Apollo公共空间中EDU001.sentinel-rules读取限流规则
spring.cloud.sentinel.datasource.flow.apollo.namespace-name = ${sentinel.datasource.rules.apollo.namespace-name}
# 限流规则的具体内容,具体写法下文会介绍(我们需要再添加一个key为“myApplication-flow-rules”的属性存放具体的限流规则)
spring.cloud.sentinel.datasource.flow.apollo.flowRulesKey = ${spring.application.name}-${spring.cloud.sentinel.datasource.flow.apollo.ruleType}-rules
# 规则类型:熔断降级
spring.cloud.sentinel.datasource.degrade.apollo.ruleType = degrade
# 从Apollo公共空间中EDU001.sentinel-rules读取熔断规则
spring.cloud.sentinel.datasource.degrade.apollo.namespace-name = ${sentinel.datasource.rules.apollo.namespace-name}
# 熔断降级规则的具体内容,具体写法下文会介绍
spring.cloud.sentinel.datasource.degrade.apollo.flowRulesKey = ${spring.application.name}-${spring.cloud.sentinel.datasource.degrade.apollo.rule-ruleType}-rules
push 模式:即推模式,由规则中心统一推送, Sentinel Client 通过注册监听器的方式时刻监听变化,比如使用 Nacos、Apollo、ZooKeeper 等配置中心,这种方式有更好的实时性和一致性保证。生产环境下推荐采用 push 模式的数据源,push 推送的操作应该由 Sentinel dashboard 和 Config Center Dashboard 控制台统一进行管理和推送,不应该经 Sentinel Client 推送至配置中心,Sentinel Client 仅负责获取配置中心推送的配置并更新到本地,因此推送规则正确做法应该是:配置中心控制台/Sentinel 控制台 → 配置中心 → Sentinel 客户端。
单纯通过上面配置只能实现apollo更改同步到图形化界面,实现不了图形化界面更改同步到apollo,需要调整代码,具体怎么实现可以看文章:Sentinel 规则持久化到 apollo 配置中心
网友评论