原文地址
http://t.zoukankan.com/exce-ben-p-13501972.html
问题描述
整合SpringCloud alibaba Sentinel 时发现一个意想不到的事情,那就是设置拦截资源,自定义返回结果的时候WebCallbackManager无法导入。
问题根因
之前的sentinel版本升级,高版本都是能兼容低版本的,可是这次2.2.0的升级不知道为啥,就是没兼容低版本的sentinel,
2.2.0之前的版本基于sentinel-web-servlet原生servlet能力实现
2.2.0及之后版本是依赖 sentinel-spring-webmvc-dapter,基于 Spring 的 Interceptor 拦截资源,不再是 CommonFilter。
- 实现接口发现变化
// 之前版本
public class UrlBlockHandler implements UrlBlockHandler {
@Override
public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException e) throws IOException {
// 降级业务处理
}
}
// v2.2.0
public class UrlBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
// 降级业务处理
}
}
- 请求解析器实现接口的包发生变化
//旧版本
import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
// v2.2.0
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
// 请求解析器实现
public class HeaderRequestOriginParser implements RequestOriginParser {
private static final String ALLOW = "Allow";
@Override
public String parseOrigin(HttpServletRequest request) {
return request.getHeader(ALLOW);
}
}
注意
1. 默认情况下只拦截 / 请求。注意:只有斜杠后面只有一个*
上文提到V2.2.0 是基于 Interceptor 实现,默认拦截规则为 /*, 也就是只有 请求URI 为 / ,/a
的请求可以被sentinel处理,/a/b
的请求会被忽略,dashboard 也只会显示被拦截的资源,需要配置一下拦截规则。
spring:
cloud:
sentinel:
filter:
url-patterns: /**
2. 默认情况: spring boot admin 显示部分服务为 down,控台只显示部分服务
访问服务 IP:PORT/actuator/health 显示sentinel 状态为 down,默认情况下 sentinel 是懒加载的,在启动时不会立即给 sentinel-server 发送心跳,导致SentinelHealthIndicator 将状态判为 false ,进而导致 Spring Boot Admin 读取到 actuator 信息为 down
可以设置饥饿加载,启动加载时就会加载,并发送心跳
spring:
cloud:
sentinel:
eager: true
解决方案
方案一
2.2.0之前版本写法
@Configuration
public class SentinelConfig {
public SentinelConfig() {
WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
@Override
public void blocked(HttpServletRequest request, HttpServletResponse response,
// 降级业务处理
}
});
}
}
改为
@Component
public class SentinelUrlBlockHandler implements BlockExceptionHandler {
/**
* 自定义限流返回信息
*/
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
// 降级业务处理
}
}
方案二
如果非要用WebCallbackManager,加一套依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-web-servlet</artifactId>
</dependency>