一、什么是Sentinel
Sentinel是Alibaba开源的,面向分布式服务架构的高可用组件。其拥有多维度的流控降级能力,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者稳定微服务的稳定性。我们可以通过官网的文档了解到更多。
二、依赖引入配置
这里只是使用了单纯的Sentinel,并没有整合SpringCloudAlibaba,后面会写到整合到SpringCloudAlibaba框架的项目中。
依赖引入
1 2 3 4 5 6 7 8 9 10
| <dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-core</artifactId> </dependency>
<dependency> <groupId>com.alibaba.csp</groupId> <artifactId>sentinel-annotation-aspectj</artifactId> </dependency>
|
如果要使用Sentinel的注解还需要将SentinelResourceAspect类型的bean加入到spring的容器中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@Component public class SentinelConfig {
@Bean public SentinelResourceAspect sentinelResourceAspect() { return new SentinelResourceAspect(); } }
|
三、基于代码控流和降级的示例
这里只演示简单的流控和降级的代码示例,值得注意的是 流控规则一般在被调用端 而 熔断降级规则一般在调用端
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
@Slf4j @RestController @RequestMapping(value = "/sentinel") public class SentinelController {
private static final String RESOURCE_NAME = "hello";
private static final String USER_RESOURCE_NAME = "user";
private static final String DEGRADE_RESOURCE_NAME = "degrade";
@GetMapping("/hello") public String hello() { Entry entry = null; try { entry = SphU.entry(RESOURCE_NAME); String result = "Hello World!"; log.info(result); return result; } catch (BlockException e) { log.info("被限流了"); return "被流控了!"; } catch (Exception e) { Tracer.traceEntry(e, entry); }finally { if (entry != null) { entry.exit(); } } return null; }
@GetMapping("/user") @SentinelResource(value = USER_RESOURCE_NAME, blockHandler = "blockHandleForUser") public String user(String id) { log.info("user:" + id); return "user"; }
public String blockHandleForUser(String id, BlockException e) { e.printStackTrace(); log.info("user被流控了"); return "user被流控了"; }
@GetMapping("/degrade") @SentinelResource(value = DEGRADE_RESOURCE_NAME, entryType = EntryType.IN, blockHandler = "blockHandleForDegrade") public String degrade() { int s = 1 / 0; return "degrade"; }
public String blockHandleForDegrade(BlockException e) { e.printStackTrace(); log.info("user被熔断了"); return "user被熔断了"; }
@PostConstruct private static void initFlowRules() { List<FlowRule> rules = new ArrayList<>(); FlowRule ruleHello = new FlowRule(); ruleHello.setResource(RESOURCE_NAME); ruleHello.setGrade(RuleConstant.FLOW_GRADE_QPS); ruleHello.setCount(1); rules.add(ruleHello);
FlowRule ruleUser = new FlowRule(); ruleUser.setResource(USER_RESOURCE_NAME); ruleUser.setGrade(RuleConstant.FLOW_GRADE_QPS); ruleUser.setCount(1); rules.add(ruleUser); FlowRuleManager.loadRules(rules);
}
@PostConstruct public void initDegradeRule() { List<DegradeRule> list = new ArrayList<>(); DegradeRule degradeRule = new DegradeRule(); degradeRule.setResource(DEGRADE_RESOURCE_NAME); degradeRule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT); degradeRule.setCount(2); degradeRule.setTimeWindow(10); degradeRule.setMinRequestAmount(2); degradeRule.setStatIntervalMs(60 * 1000); list.add(degradeRule);
DegradeRuleManager.loadRules(list);
}
}
|
到这里简单的通过代码方式定义流控和熔断降级规则的示例就完成了,可以通过调用下面的接口测试:
- 基于catch的方式捕获流控:xxxxxxxx/hello
- 基于@SentinelResource 的方式捕获流控:xxxxxxx/user
- 熔断降级:xxxxxxx/degrade
四、整合到SpringCloudAlibaba架构的项目中
这里可以参考SpringCloudAlibaba的官方文档来做
1、引入依赖
这里先将我们之前引入的依赖注释掉,在加入👇🏻的依赖,在测试一下依然是可以实现上面的流控和熔断降级规则的。
1 2 3 4
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
|
2、加入Sentinel 控制台
我们可以从sentinel tag页面获取到想要的版本
通过一下命令启动sentinel dashboard服务,可以根据我们的实际情况修改端口,更多用法及参数可以查看sentinel-dashboard文档
1
| java -Dserver.port=8858 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar
|
访问8858端口就可以进入到控制台页面了

3、将服务注册进入到Sentinel控制台中
一共有两种方式,分别是通过启动参数配置和通过yml文件配置
通过启动参数配置:在启动参数中添加-Dcsp.sentinel.dashboard.server=sentinel服务的ip:8858

当我们启动后会发现服务并没有注册到Sentinel的控制台中,这时我们只需要访问几次要注册进去的服务的接口,你就会发现服务已经注册到Sentinel中了

通过yml配置:在yml中添加👇🏻配置,这里要注意client-ip的不要写错,我就因为没有写和写成了Sentinel服务端的ip导致应用服务注册不到Sentinel,卡了一晚上
1 2 3 4 5 6 7 8 9 10
| spring: cloud: sentinel: transport: client-ip: 192.168.0.101 dashboard: 192.168.0.107:8858 eager: true
|

五、整合OpenFeign
1、添加相关依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>${alibaba.sentinel.version}</version> </dependency>
|
上面三个依赖是必须的。
2、配置yml配置文件
开启OpenFeign对Sentinel的支持
1 2 3
| feign: sentinel: enabled: true
|
3、实现你的OpenFeign接口类
1 2 3 4 5 6 7 8 9 10 11 12
| @Component public class StockSentinelFallback implements Stock{ @Override public String reduceStock() { return null; }
@Override public String reduceStock2() { return "降级了2"; } }
|
4、修改对应的OpenFeign接口类
只需要在@FeignClient
注解中增加fallback入参即可,指定实现类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @FeignClient(name = "stock", path = "/stock", fallback = StockSentinelFallback.class) public interface Stock {
@PostMapping(value = "/reduceStock") public String reduceStock();
@PostMapping(value = "/reduceStock2") public String reduceStock2(); }
|
上面的代码中/reduceStock2
是用于做降级熔断测试的接口,所以在测试类中只写了reduceStock2的返回值。
问题记录
本地服务无法注册到服务器的Sentinel dashboard中
这个问题可能有以下几种原因,这里只写我遇到的:
yml
配置文件中的 client-ip
配置项没有配置或者配置错误,这个配置项在上面有提到过,是配置你的服务所在ip,如果Sentinel dashboard和服务是在一台机器启动的则可以忽略这个配置
版本对应的问题,我一直以为官方的版本对应应该是没有问题的。各种怀疑自己的配置或者网络问题。突然想起版本对应才发现这个问题,spring-cloud-alibaba-dependencies:2.2.9.RELEASE
对应spring-cloud-starter-alibaba-sentinel:2.2.8.RELEASE
,这个是经过我不懈测试后可以正常将服务注册到Sentinel dashboard中的版本