本来大型服务处理请求超时,限流,降级熔断工作用hystrix,但是这个这个项目不再更新了,虽说它现在提供的版本不会影响到大多数开发者的使用,但是长远考虑,被更换是一件必然的事,而且现在像resilience4j, Sentinel这样的替代品出现,今天我们就看看使用zuul 与 Sentinel整合,实现降级与超时处理,其实网上有很多这样的教程,这里我只是做一个自己的笔记而已
1.必须的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-zuul-adapter</artifactId>
<version>1.7.1</version>
</dependency>
-
配置文件,其实Sentinel在这里没什么配置
server: port: 6001 spring: application: name: e-zuul eureka: instance: hostname: localhost lease-expiration-duration-in-seconds: 90 #表示服务端多长时间没有接受到心跳信息后可以删除自己 lease-renewal-interval-in-seconds: 30 #表示需要要向服务端发送信息,表示自己还活着 ip-address: true client: healthcheck: enabled: true #客户端心跳检测 service-url: defaultZone: http://${eureka.instance.hostname}:3001/eureka/ zuul: add-proxy-headers: true LogFilter: pre: disable=true: routes: e-email: serviceId: e-email path: /email/** e-user: serviceId: e-user path: /user/**
-
配置类, 其实配置类和后边的降级回调处理类才是关键,而且配置类中几个关于zuul与Sentinel的过滤器非常关键,这里要是不提供它们,将无法实现我们想要的功能,还有就是网关规则,可以选择qps, 超时,线程等,setGrade(RuleConstant.DEGRADE_GRADE_RT)提供选择不同的策略
package com.mjlf.ezuul.config; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager; import com.alibaba.csp.sentinel.adapter.gateway.zuul.fallback.ZuulBlockFallbackManager; import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulErrorFilter; import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPostFilter; import com.alibaba.csp.sentinel.adapter.gateway.zuul.filters.SentinelZuulPreFilter; import com.alibaba.csp.sentinel.slots.block.RuleConstant; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule; import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager; import com.netflix.zuul.ZuulFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; import java.util.HashSet; import java.util.Set; @Configuration public class ZuulConfig { @Bean public ZuulFilter sentinelZuulPreFilter() { // We can also provider the filter order in the constructor. return new SentinelZuulPreFilter(); } @Bean public ZuulFilter sentinelZuulPostFilter() { return new SentinelZuulPostFilter(); } @Bean public ZuulFilter sentinelZuulErrorFilter() { return new SentinelZuulErrorFilter(); } @PostConstruct public void doInit() { // 注册 FallbackProvider ZuulBlockFallbackManager.registerProvider(new MyBlockFallbackProvider()); initGatewayRules(); } /** * 配置限流规则 */ private void initGatewayRules() { Set<GatewayFlowRule> rules = new HashSet<>(); rules.add(new GatewayFlowRule("e-user").setCount(3) // 限流阈值 .setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒 ); rules.add(new GatewayFlowRule("e-user") .setGrade(RuleConstant.DEGRADE_GRADE_RT)//设置超时类型规则 .setMaxQueueingTimeoutMs(500) ); GatewayRuleManager.loadRules(rules); } }
-
回调处理类,当有请求被拦截到后,就会调用降级回调方法
// 自定义 FallbackProvider
@Component
public class MyBlockFallbackProvider implements ZuulBlockFallbackProvider {
private Logger logger = LoggerFactory.getLogger(DefaultBlockFallbackProvider.class);
// you can define route as service level
@Override
public String getRoute() {
return "*";
}
@Override
public BlockResponse fallbackResponse(String route, Throwable cause) {
RecordLog.info(String.format("[Sentinel DefaultBlockFallbackProvider] Run fallback route: %s", route));
if (cause instanceof BlockException) {
return new BlockResponse(429, "Sentinel block exception", route);
} else {
return new BlockResponse(500, "System Error", route);
}
}
}