Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量控制、流量路由、熔断降级、系统自适应保护等多个维度来帮助用户保障微服务的稳定性。
—— 引自Sentinel官网
Sentinel支持两种资源维度的限流:
com.alibaba.csp sentinel-spring-cloud-gateway-adapter
@Configuration@AllArgsConstructorpublic class GatewayConfig { private final List viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } // 配置限流异常处理器,即触发限流后的默认处理类 @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public CustomSentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new CustomSentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } @PostConstruct public void doInit() { initGatewayRules(); } // 初始化限流规则 private void initGatewayRules() { Set rules = new HashSet<>(); GatewayFlowRule gatewayFlowRule = new GatewayFlowRule("jasmine-auth"); gatewayFlowRule.setCount(1D); gatewayFlowRule.setIntervalSec(5L); rules.add(gatewayFlowRule); GatewayRuleManager.loadRules(rules); }}
在实际的应用中(笔者接触的项目大体是前后端分离的),我们通常以JSON的格式返回数据。我们自定义了一个异常处理器,当触发限流时返回JSON格式的异常数据。
public class CustomSentinelGatewayBlockExceptionHandler implements WebExceptionHandler { private final List viewResolvers; List> messageWriters; public CustomSentinelGatewayBlockExceptionHandler(List viewResolvers, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolvers; this.messageWriters = serverCodecConfigurer.getWriters(); } private Mono writeResponse(ServerResponse response, ServerWebExchange exchange) { ServerHttpResponse serverHttpResponse = exchange.getResponse(); serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8"); Map map = new HashMap<>(); map.put("code", 500); map.put("msg", "访问人数过多!"); DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(new Gson().toJson(map).getBytes(StandardCharsets.UTF_8)); return serverHttpResponse.writeWith(Mono.just(dataBuffer)); } // 省略无关代码}
自定义全局限流异常处理器的代码是直接从SentinelGatewayBlockExceptionHandler中复制过来,我们只修改writeResponse方法,该方法的作用是将限流的异常信息写回客户端。
配置类的主要功能如下:
网关限流规则(GatewayFlowRule)中提供了如下属性:
server: port: 9010spring: profiles: active: dev application: name: jasmine-sentinel cloud: nacos: config: file-extension: yaml group: ${spring.profiles.active} prefix: ${spring.application.name} server-addr: 127.0.0.1:8848 gateway: discovery: locator: enabled: true # 是否使用service-id的小写,默认是大写 lower-case-service-id: true routes: - id: jasmine-auth uri: lb://jasmine-auth predicates: - Path=/auth/**
关键配置说明:
最后在浏览器中访问http://127.0.0.1:9010/auth/hello,多次刷新,当触发限流规则时看到的返回结果如下所示:
{"msg":"访问人数过多!","code":500}
自定义API分组限流可以让多个Route共用一个限流规则。
自定义Api分组限流
// 自定义Api分组限流private void initCustomizedApis() { Set definitions = new HashSet<>(); ApiDefinition apiDefinition = new ApiDefinition("jasmine-customized-api") .setPredicateItems(new HashSet() {{ add(new ApiPathPredicateItem().setPattern("/auth/**")); add(new ApiPathPredicateItem().setPattern("/log/**") .setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX)); }}); definitions.add(apiDefinition); GatewayApiDefinitionManager.loadApiDefinitions(definitions);}
上述代码主要是将/auth/**和/log/**进行统一分组,并提供一个name=jasmine-customized-api,然后在初始化网关限流规则时,针对该name设置限流规则。同时,我们可以通过setMatchStrategy来设置不同path下的限流参数策略。
// 初始化限流规则private void initGatewayRules() { Set rules = new HashSet<>(); GatewayFlowRule gatewayFlowRule = new GatewayFlowRule("jasmine-customized-api"); gatewayFlowRule.setCount(1D); gatewayFlowRule.setIntervalSec(5L); gatewayFlowRule.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME); rules.add(gatewayFlowRule); GatewayRuleManager.loadRules(rules);}
initCustomizedApis()方法和initGatewayRules()方法一样,在初始化的时候调用。
@PostConstructpublic void doInit() { initCustomizedApis(); initGatewayRules();}
这样,我们在浏览器中访问http://127.0.0.1:9010/auth/hello和http://127.0.0.1:9010/log/hello,多次刷新,都会触发限流规则,然后看到的返回结果如下所示:
{"msg":"访问人数过多!","code":500}
图片引自官网。
留言与评论(共有 0 条评论) “” |