本项目演示如何使用 Sentinel starter 完成 Spring Cloud 应用的限流管理。
Sentinel 是阿里巴巴开源的分布式系统的流量防卫组件,Sentinel 把流量作为切入点,从流量控制,熔断降级,系统负载保护等多个维度保护服务的稳定性。
com.alibaba.cloud spring-cloud-starter-alibaba-sentinel
HTTP 埋点
Sentinel starter 默认为所有的 HTTP 服务提供了限流埋点,如果只想对 HTTP 服务进行限流,那么只需要引入依赖,无需修改代码。
自定义埋点
如果需要对某个特定的方法进行限流或降级,可以通过 @SentinelResource 注解来完成限流的埋点,示例代码如下:
@SentinelResource("resource")public String hello() {return "Hello";}
当然也可以通过原始的 SphU.entry(xxx) 方法进行埋点:
Entry entry = null;
// 务必保证 finally 会被执行
try {// 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名// EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效entry = SphU.entry("自定义资源名");// 被保护的业务逻辑// do something...
} catch (BlockException ex) {// 资源访问阻止,被限流或被降级// 进行相应的处理操作
} catch (Exception ex) {// 若需要配置降级规则,需要通过这种方式记录业务异常Tracer.traceEntry(ex, entry);
} finally {// 务必保证 exit,务必保证每个 entry 与 exit 配对if (entry != null) {entry.exit();}
}
Sentinel 提供了两种配置限流规则的方式:代码配置 和 控制台配置。本示例使用的方式为通过控制台配置。
通过代码来实现限流规则的配置。一个简单的限流规则配置示例代码如下:
List rules = new ArrayList();
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);
参考:https://doker.blog.csdn.net/article/details/128515967
增加配置,在应用的 /src/main/resources/application.properties 中添加基本配置信息
spring.application.name=sentinel-example
server.port=18083
spring.cloud.sentinel.transport.dashboard=localhost:8080
启动应用,支持 IDE 直接启动和编译打包后启动。
IDE直接启动:找到主类 ServiceApplication,执行 main 方法启动应用。
打包编译后启动:首先执行 mvn clean package 将工程编译打包,然后执行 java -jar sentinel-core-example.jar启动应用。
使用 curl 分别调用两个 URL,可以看到访问成功。
访问 http://localhost:8080 页面,可以在左侧看到 Sentinel-Example 应用已经注册到了控制台,单击 流控规则 ,可以看到目前的流控规则为空。
注意:如果您在控制台没有找到应用,请调用一下进行了 Sentinel 埋点的 URL 或方法,因为 Sentinel 使用了 lazy load 策略
配置 URL 限流规则:点击新增流控规则,资源名填写需要限流的 URL 相对路径,单机阈值选择需要限流的阈值,点击新增进行确认。(为了便于演示效果,这里将值设置成了 1)。
配置自定义限流规则:点击新增流控规则,资源名填写 @SentinelResource 注解 value 字段的值,单机阈值选择需要限流的阈值,点击新增进行确认。(为了便于演示效果,这里将值设置成了 1)。
访问 URL,当 QPS 超过 1 时,可以看到限流效果如下。
默认限流异常处理
URL 限流触发后默认处理逻辑是,直接返回 "Blocked by Sentinel (flow limiting)"。 如果需要自定义处理逻辑,实现的方式如下:
public class CustomUrlBlockHandler implements UrlBlockHandler {@Overridepublic void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException {// todo add your logic}
}WebCallbackManager.setUrlBlockHandler(new CustomUrlBlockHandler());
使用 @SentinelResource 注解下的限流异常处理
如果需要自定义处理逻辑,填写 @SentinelResource 注解的 blockHandler 属性(针对所有类型的 BlockException,需自行判断)或 fallback 属性(针对熔断降级异常),注意对应方法的签名和位置有限制,示例实现如下:
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;}
}
Spring Boot 应用支持通过 Endpoint 来暴露相关信息,Sentinel Starter 也支持这一点。
在使用之前需要在 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。
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=jsonspring.cloud.sentinel.datasource.ds2.nacos.server-addr=localhost: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
s1 和 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
上一篇:《音视频:给图片添加黑色边框》
下一篇:一些关于S参数常见问题的问答