14 KiB
Spring Cloud Alibaba Sentinel Example
项目说明
本 Example 项目演示如何使用 spring-cloud-starter-alibaba-sentinel
完成 Spring Cloud 应用中的流量治理功能。
Sentinel 是阿里巴巴开源的分布式系统的流量防卫组件,Sentinel 以流量作为切入点,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。
Sentinel Example
在本 Example 项目中,主要演示 Sentinel 断路器,整合 Spring Cloud Gateway 和 OpenFeign、RestTemplate 以及 Webclient 的使用。
下载并启动 Sentinel Console
-
首先需要获取 Sentinel 控制台,Sentinel Console 支持直接下载和源码构建两种方式
- 直接下载:下载 Sentinel 控制台
- 源码构建:进入 Sentinel Github 项目页面,将代码 clone 到本地自行编译打包,参考此文档。
-
启动控制台,执行 Java 命令
java -jar sentinel-dashboard.jar
完成 Sentinel 控制台的启动。控制台默认的监听端口为
8080
。Sentinel 控制台使用 Spring Boot 编程模型开发,如果需要指定其他端口,请使用 Spring Boot 容器配置的标准方式,详情请参考 Spring Boot 文档。
Sentinel Core Example
在此 Example 模块中,主要演示如何使用 Sentinel 的基本功能完成 Spring Cloud 应用的流量管控。 在启动 Example 进行演示之前,先了解一下如何在 Spring Cloud 应用中接入 Sentinel 组件。
项目编写
注意:本文档只是为了便于理解接入方式。本示例代码中已经完成接入工作,您无需再进行修改。
-
首先,修改
pom.xml
文件,引入 Sentinel starter。<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency>
-
接入限流埋点
-
HTTP 埋点
spring-cloud-starter-alibaba-sentinel
默认为所有的 HTTP 服务提供了限流埋点,如果只想对 HTTP 服务进行限流,那么只需要引入依赖,无需修改代码。 -
自定义埋点 如果需要对某个特定的方法进行限流或降级,可以通过
@SentinelResource
注解来完成限流的埋点,示例代码如下:@SentinelResource("resource") public String hello() { return "Hello"; }
当然也可以通过原始的
SphU.entry(xxx)
方法进行埋点,可以参见 Sentinel 文档。 -
-
配置限流规则
Sentinel 提供了两种配置限流规则的方式:代码配置 和 控制台配置。本示例使用的方式为通过代码配置。
-
通过代码来实现限流规则的配置。一个简单的限流规则配置示例代码如下,更多限流规则配置详情请参考 Sentinel 文档。
List<FlowRule> rules = new ArrayList<FlowRule>(); FlowRule rule = new FlowRule(); rule.setResource(str); // set limit qps to 10 rule.setCount(10); rule.setGrade(RuleConstant.FLOW_GRADE_QPS); rule.setLimitApp("default"); rules.add(rule); FlowRuleManager.loadRules(rules);
-
通过控制台进行限流规则配置请参考文章后面的图文说明。
-
应用启动
-
增加配置,在应用的
/src/main/resources/application.yml
中添加基本配置信息server: port: 18083 spring: application: name: sentinel-core-example cloud: sentinel: transport: dashboard: localhost:8080
-
启动应用,支持 IDE 直接启动和编译打包后启动。
- IDE直接启动:找到主类
SentinelCoreApplication
,执行 main 方法启动应用。 - 打包编译后启动:首先执行
mvn clean package
将工程编译打包,然后执行java -jar sentinel-core-example.jar
启动应用。
- IDE直接启动:找到主类
调用服务验证
使用 curl 命令分别调用两个 URL,可以看到访问成功。
$ curl http://localhost:18083/test
Blocked by Sentinel (flow limiting)
$ curl http://localhost:18083/hello
Hello
配置限流规则并验证
-
访问 http://localhost:8080 页面,进行登陆,默认用户名和密码均为:
sentinel
。可以在左侧看到
sentinel-core-example
应用已经注册到了控制台,单击 流控规则 ,可以看到目前的流控规则为空。注意:如果您在控制台没有找到应用,请调用一下进行了 Sentinel 埋点的 URL 或方法,因为 Sentinel 使用了 lazy load 策略。详细的排查过程请参见 Sentinel FAQ。
- 配置 URL 限流规则:点击新增流控规则,资源名填写需要限流的 URL 相对路径,单机阈值选择需要限流的阈值,点击新增进行确认。(为了便于演示效果,这里将值设置成了 1)。
- 配置自定义限流规则:点击新增流控规则,资源名填写
@SentinelResource
注解value
字段的值,单机阈值选择需要限流的阈值,点击新增进行确认。(为了便于演示效果,这里将值设置成了 1)。
自定义限流处理逻辑
-
默认限流异常处理
URL 限流触发后默认处理逻辑是,直接返回 "Blocked by Sentinel (flow limiting)"。 如果需要自定义处理逻辑,实现的方式如下:
public class CustomUrlBlockHandler implements UrlBlockHandler { @Override public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException { // todo add your logic } } WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());
-
使用
@SentinelResource
注解下的限流异常处理如果需要自定义处理逻辑,填写
@SentinelResource
注解的blockHandler
属性(针对所有类型的BlockException
,需自行判断)或fallback
属性(针对熔断降级异常),注意对应方法的签名和位置有限制,详情见 Sentinel 注解支持文档。示例实现如下:public class TestService { // blockHandler 是位于 ExceptionUtil 类下的 handleException 静态方法,需符合对应的类型限制. @SentinelResource(value = "test", blockHandler = "handleException", blockHandlerClass = {ExceptionUtil.class}) public void test() { System.out.println("Test"); } // blockHandler 是位于当前类下的 exceptionHandler 方法,需符合对应的类型限制. @SentinelResource(value = "hello", blockHandler = "exceptionHandler") public String hello(long s) { return String.format("Hello at %d", s); } public String exceptionHandler(long s, BlockException ex) { // Do some log here. ex.printStackTrace(); return "Oops, error occurred at " + s; } } public final class ExceptionUtil { public static void handleException(BlockException ex) { System.out.println("Oops: " + ex.getClass().getCanonicalName()); } }
一个简单的 @SentinelResource
示例可以见 sentinel-demo-annotation-spring-aop。
Sentinel Circuitbreaker Example
本 Example 主要演示 OpenFeign 整合 Sentinel 断路器的使用。
准备配置文件
-
添加配置到配置中心。dataId 为
sentinel-circuitbreaker-rules.yml
feign: circuitbreaker: enabled: true # 开启 feign 断路器支持 sentinel: default-rule: default # 默认规则名称 rules: # 默认规则, 对所有 feign client 生效 default: - grade: 2 # 根据异常数目降级 count: 1 timeWindow: 15 # 降级后到半开状态的时间 statIntervalMs: 1000 minRequestAmount: 1 # 只对 feign client user 生效 user: - grade: 2 count: 1 timeWindow: 15 statIntervalMs: 1000 minRequestAmount: 1 # 只对 feign client user 的方法 feignMethod 生效 # 括号里是参数类型, 多个逗号分割, 比如 user#method(boolean,String,Map) "[user#feignMethod(boolean)]": - grade: 2 count: 1 timeWindow: 10 statIntervalMs: 1000 minRequestAmount: 1
验证配置生效
启动项目主类 FeignCircuitBreakerApplication
验证默认 Feign client 生效
先访问 http://localhost/test/default/false 2 次 (1秒内)
再访问 http://localhost/test/default/true 断路器处于打开状态
验证指定 Feign client 生效
先访问 http://localhost/test/feign/false 2 次 (1秒内)
再访问 http://localhost/test/feign/true 断路器处于打开状态
验证 Feign client 指定方法生效
先访问 http://localhost/test/feignMethod/false 2次 (1秒内)
再访问 http://localhost/test/feignMethod/true 断路器处于打开状态
规则动态刷新
修改配置中心的规则, 再访问上述接口。
Sentinel OpenFeign Example
本 Example 演示 OpenFeing 与 Sentinel 的整合。Example 中使用 httpbin 充当后台 API 接口服务。
项目编写
注意:本项目中代码已经完成相对应的功能,不需要再进行任何修改。
项目支持两种启动方式:通过主类 OpenFeignApplication
启动和 Jar 包启动两种方式。
调用测试
项目启动完成之后,可以通过访问对应的 URL 访问,查看对应的 Sentinel 流控效果。
注意:项目中提供的 RestTemplate 和 Webclient Example 同理。
Endpoint 信息查看
Spring Boot 应用支持通过 Endpoint 来暴露相关信息,spring-cloud-starter-alibaba-sentinel
也支持这一点。
在使用之前需要在 Maven 中添加 spring-boot-starter-actuator
依赖,并在配置中允许 Endpoints 的访问。
- Spring Boot 1.x 中添加配置
management.security.enabled=false
- Spring Boot 2.x 中添加配置
management.endpoints.web.exposure.include=*
Spring Boot 1.x 可以通过访问 http://127.0.0.1:18083/sentinel 来查看 Sentinel Endpoint 的信息。Spring Boot 2.x 可以通过访问 http://127.0.0.1:18083/actuator/sentinel 来访问。
查看实时监控
Sentinel 控制台支持实时监控查看,您可以通过 Sentinel 控制台查看各链路的请求的通过数和被限流数等信息。
其中 p_qps
为通过(pass) 流控的 QPS,b_qps
为被限流 (block) 的 QPS。
ReadableDataSource 支持
Sentinel 内部提供了动态规则的扩展实现 ReadableDataSource。
Sentinel starter 整合了目前存在的几类 ReadableDataSource。只需要在配置文件中进行相关配置,即可在 Spring 容器中自动注册 DataSource。
比如要定义两个ReadableDataSource,分别是 FileRefreshableDataSource
和 NacosDataSource
,配置如下:
spring.cloud.sentinel.datasource.ds1.file.file=classpath: degraderule.json
spring.cloud.sentinel.datasource.ds1.file.data-type=json
spring.cloud.sentinel.datasource.ds2.nacos.server-addr=127.0.0.1:8848
spring.cloud.sentinel.datasource.ds2.nacos.dataId=sentinel
spring.cloud.sentinel.datasource.ds2.nacos.groupId=DEFAULT_GROUP
spring.cloud.sentinel.datasource.ds2.nacos.data-type=json
ds1
和 ds2
表示ReadableDataSource的名称,可随意编写。ds1
和 ds2
后面的 file
和 nacos
表示ReadableDataSource的类型。
目前支持file
, nacos
, zk
, apollo
,redis
这5种类型。
其中nacos
,zk
,apollo
,redis
这4种类型的使用需要加上对应的依赖sentinel-datasource-nacos
, sentinel-datasource-zookeeper
, sentinel-datasource-apollo
, sentinel-datasource-redis
。
当 ReadableDataSource
加载规则数据成功的时候,控制台会打印出相应的日志信息:
[Sentinel Starter] DataSource ds1-sentinel-file-datasource load 3 DegradeRule
[Sentinel Starter] DataSource ds2-sentinel-nacos-datasource load 2 FlowRule
More
Sentinel 是一款功能强大的中间件,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。此 Demo 仅演示了 使用 Sentinel 作为限流工具的使用,更多 Sentinel 相关的信息,请参考 Sentinel 项目。
如果您对 spring-cloud-starter-alibaba-sentinel
有任何建议或想法,欢迎在 issue 中或者通过其他社区渠道向我们提出。