sentinel 学习笔记
前段时间大致用了一下sentinel。但是阿里云的sentinel开源并没有实现持久化,针对这个问题我采用了apollo去实现sentinel的持久化。下面就记录一下实现sentinel持久化的过程。
Sentinel 是什么?
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。
如何使用sentinel?
对于初学者来说,使用sentinel只需要限流功能就可以了,所以在本篇文章中,仅针对SpringCloud项目的限流功能进行阐述。
开启sentinel控制台
可以先去官网下载源代码,然后在本地打开sentinel控制台,账号密码都是sentinel,端口是8001(都可以在application配置里面改)
打开后如图所示,因为没有任何服务连接sentinel控制台,所以现在是一片空白。
开启一个项目连接sentinel控制台
开启一个SpringCloud项目,写一个最简单的controller
添加sentinel依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>0.9.0.RELEASE</version>
</dependency>
添加application配置
# port settings
server:
port: 8081
spring:
application:
name: sentinel-web-demo
cloud:
sentinel:
transport:
dashboard: localhost:8001 # sentinel客户端服务的地址
eager: true
这时候再登录sentinel就可以看到名为sentinel-web-demo
的服务注册上去了
sentinel实现限流
如图所示,在流控规则下新增一个流控规则,资源名中填写请求路径,然后设置阈值就可以了。
成功时正常显示,失败时则会输出提示信息。
是的,完成了这步我们就实现了最简单的sentinel控流。
sentinel的持久化
很快我们就能发现存在这样的问题,一旦服务器或者客户端重启了,sentinel的控流规则就失效了。这对于一个上线的项目来说无疑是致命的,万一机器出现故障,那么我们大量的sentinel控流规则都会消失。这是因为开源的sentinel控流规则是存储在内存中的,我们需要通过一些方法来实现sentinel的持久化,在这里就只简单说一下使用apollo实现sentinel持久化。
感兴趣的同学可以看一下官方的文档
推送模式 | 说明 | 优点 | 缺点 |
---|---|---|---|
原始模式 | API 将规则推送至客户端并直接更新到内存中,扩展写数据源(WritableDataSource ) |
简单,无任何依赖 | 不保证一致性;规则保存在内存中,重启即消失。严重不建议用于生产环境 |
Pull 模式 | 扩展写数据源(WritableDataSource ), 客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件 等 |
简单,无任何依赖;规则持久化 | 不保证一致性;实时性不保证,拉取过于频繁也可能会有性能问题。 |
Push 模式 | 扩展读数据源(ReadableDataSource ),规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。生产环境下一般采用 push 模式的数据源。 |
规则持久化;一致性;快速 | 引入第三方依赖 |
sentinel 控制台代码改造
pom.xml文件先把Apollo包的test作用域去掉,顺便log4j更新成 2.15(防止恶意代码注入)
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-openapi</artifactId>
<version>1.2.0</version>
<!-- <scope>test</scope>-->
</dependency>
写一个Apollo的config,Converter<T,S>指的是将S转换为T类型,portalUrl是Apollo的地址,token是Apollo生成的token
public class ApolloConfig {
@Value("${apollo.meta}")
private String portalUrl;
@Value("${apollo.token}")
private String token;
/**
* 流控规则编码
*
* @return
*/
@Bean
public Converter<List<FlowRuleEntity>, String> flowRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 流控规则解码
*
* @return
*/
@Bean
public Converter<String, List<FlowRuleEntity>> flowRuleEntityDecoder() {
return s -> JSON.parseArray(s, FlowRuleEntity.class);
}
/**
* 降级规则编码
*
* @return
*/
@Bean
public Converter<List<DegradeRuleEntity>, String> degradeRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 降级规则解码
*
* @return
*/
@Bean
public Converter<String, List<DegradeRuleEntity>> degradeRuleEntityDecoder() {
return s -> JSON.parseArray(s, DegradeRuleEntity.class);
}
/**
* 授权规则编码
*
* @return
*/
@Bean
public Converter<List<AuthorityRuleEntity>, String> authorityRuleEntityEncoder() {
return JSON::toJSONString;
}
/**
* 授权规则解码
*
* @return
*/
@Bean
public Converter<String, List<AuthorityRuleEntity>> authorityRuleEntityDecoder() {
return s -> JSON.parseArray(s, AuthorityRuleEntity.class);
}
/**
* 系统规则编码
*
* @return
*/
@Bean
public Converter<List<SystemRuleEntity>, String> systemRuleEntityEncoder