随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
Sentinel 具有以下特征:
丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。
使用Springboot整合Springcloud 实现对资源服务接口的限流操作,以及规则的持久化。
Springboot SpringCloud
Sentinel的核心依赖core
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.1</version>
</dependency>
注解切面依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.7.1</version>
</dependency>
应用程序与Sentinel控制台进行相互访问依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>1.7.1</version>
</dependency>
Sentinel的核心是资源,使用注解@SentinelResource定义资源
属性解释:
value 指的是资源的名称后续在控制台可看到资源名称
fallback 指的是回调方法,fallback函数会对所有异常类型进行捕获,除了 exceptionsToIgnore 里面排除掉的异常类型
blockHandler 函数会在原方法被限流/降级/系统保护的时候调用
blockHandlerClass blockHandler 函数所在的类
使用要求
fallback的要求
blockHandler / blockHandlerClass的要求
@RestController
public class SentinelController {
@RequestMapping(value="/test")
@SentinelResource(value="test",fallback = "fallbackMethod",blockHandlerClass = ExceptionUtil.class)
public String test(@RequestParam(value="num") int num) throws Exception {
if(num==1) {
throw new Exception();
}
return "服务成功";
}
@RequestMapping(value="test2")
@SentinelResource(value="test2",fallback = "fallbackMethod",blockHandler = "exceptionDemo")
public String test2(int num) throws BlockException{
if(num==1) {
throw new ServiceException("2");
}
return "服务成功2";
}
public String fallbackMethod(int num){
return "服务失败 本地服务返回0";
}
public String exceptionDemo(int num, BlockException e){
return "本地服务异常返回";
}
@RequestMapping(value="/Demo")
public String demo(){
return "加油";
}
}
到此步骤已经实现了Sentinel对资源的声明和异常 限流等逻辑的方法处理,可以使用硬编码的方式对资源进行控制,(参考官网)。推荐使用控制台对资源进行控制,下一步将使用控制台对资源进行规则配置。
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
自己使用java -jar 包名.jar 也启动成功了,官方这样的方式是指定jar启动时的端口吧,因为Sentinel-dashboard也是基于Springboot框架的项目内置了Tomcat
至此控制台已经完成启动
应用程序需要和Sentinel控制台进行通讯,在上面我们已经导入了相关的依赖,本地应用程序需要配置几个参数,在启动类中
访问:
-localhost:${port本地应用端口}/test2?num=2
-test是自己定义的RequestMapping的接口,num是参数
控制台已经显示了资源,我们可以通过后方按钮设置流量规则等
例子1:
这是QPS 为1 频繁调用此时会返回blockHandler的方法
@RequestMapping(value="test2")
@SentinelResource(value="test2",fallback = "fallbackMethod",blockHandler = "exceptionDemo")
public String test2(int num) throws BlockException{
if(num==1) {
throw new ServiceException("2");
}
return "服务成功2";
}
public String exceptionDemo(int num, BlockException e){
return "本地服务异常返回";
}
其他规则可以根据控制台的提示进行配置至此已经完成控制台和应用程序之间简单的资源声明和资源规则控制
Sentinel 控制台同时提供简单的规则管理以及推送的功能。规则推送分为 3 种模式,包括 “原始模式”、“Pull 模式” 和"Push 模式"。
官方介绍
官方介绍推送模式
原始模式
通过控制台配置规则,如上述所示,当应用程序重启之后规则会丢失,因为原始模式的规则存在内存当中。不安全
pull模式 拉取模式客户端主动向某个规则管理中心定期轮询拉取规则,这个规则中心可以是 RDBMS、文件,甚至是 VCS 等。这样做的方式是简单,缺点是无法及时获取变更;延迟不一致
push模式 规则中心统一推送,客户端通过注册监听器的方式时刻监听变化,比如使用 Nacos、Zookeeper 等配置中心。这种方式有更好的实时性和一致性保证。
推荐使用push模式
依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-redis</artifactId>
<version>1.7.0</version>
</dependency>
将数据源注册到RuleManage当中
实现InitFunc接口 alibaba
public class RedisInIt implements InitFunc {
@Override
public void init() throws Exception {
System.out.println("加载init方法");
Converter<String, List<FlowRule>> parser = source -> JSON.parseObject(source,new TypeReference<List<FlowRule>>() {});
//使用alibaba 构建Redisclient 并初始化
RedisConnectionConfig config = RedisConnectionConfig.builder()
.withHost("127.0.0.1")
.withPort(6379)
.build();
//放入RedisDataSource 控制台新增规则,会通过以下通道和rulekey set rulekey 到redis客户端
ReadableDataSource<String, List<FlowRule>> redisDataSource = new RedisDataSource<List<FlowRule>>
(config, "sentinel", "Test", parser );
FlowRuleManager.register2Property(redisDataSource.getProperty());
}
实现JAVA SPI规范初始化数据
首次访问资源的时候会从redis中的sentinel获取规则 数据必须是json类型,redis主要通过发布/订阅方式实现消息持久化
例如
或者使用发布
在应用程序启动之后会从Redis的String类型get key为 "sentinel"的value然后通过依赖与sentinel控制台进行通讯加载对应的资源规则。
new RedisDataSource<List<FlowRule>>
(config, "sentinel", "Test", parser );
后续也可以使用publish channel message 发布规则到通道,应用程序监听到之后发送给sentinel加载规则。
参考官方规范
可以使用存入写前端页面编辑规则,然后存入mysql 之后mysql更新成功之后放入sentinel 或者publish发布出去都可以实现。
后续讲一讲这些代码的作用。