最近基于sentinel-1.8.6搭建了一套供生产使用。在开发的过程中遇到了一些问题并进行了改造,在此记录一下。
1、http访问支持ip级别限流
如果是基于servlet容器的,可以手动复制com.alibaba.csp.sentinel.adapter.servlet.CommonFilter
,自定义一个filter,加载自定义的filter,重写com.alibaba.csp.sentinel.adapter.servlet.CommonFilter#parseOrigin
方法
private String parseOrigin(HttpServletRequest request) {String origin = IPUtils.getIpAddress(request);if (StringUtil.isEmpty(origin)) {return EMPTY_ORIGIN;}return origin;}
如果是springmvc
@Configuration
public class SentinelInterceptorConfig extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {// Add Sentinel interceptoraddSpringMvcInterceptor(registry);}private void addSpringMvcInterceptor(InterceptorRegistry registry) {SentinelWebMvcConfig config = new SentinelWebMvcConfig();config.setBlockExceptionHandler(new CustomBlockExceptionHandler());config.setHttpMethodSpecify(true);config.setWebContextUnify(true);//设置来源解析config.setOriginParser(request -> {//针对IP解析return IPUtils.getIpAddress(request);});// Add sentinel interceptorregistry.addInterceptor(new SentinelWebInterceptor(config)).addPathPatterns("/**");}
}
2、热点参数、授权规则,数据结构不一致的情况
在原有的内存方式实现,dashboard会通过调用接口方式将rule传递到客户端,
com.gongdao.csp.sentinel.dashboard.client.SentinelApiClient#executeCommand(java.lang.String, java.lang.String, int, java.lang.String, java.util.Map<java.lang.String,java.lang.String>, boolean)
但是生产lz使用的是push模式,规则配置持久化至nacos,因此也就序列化了AuthorityRuleEntity
这个实体,后来发现,授权规则,热点参数,与其他流控,熔断,系统保护规则不一致,授权/热点参数对应的序列化entity中存在rule字段,客户端进行反序列化的entity是对应的rule实体是没有rule字段,会导致rule字段丢失。
最小的改造成本就是在dashboard中保存热点参数规则以及授权规则的时候,将rule字段内的内容提升至最外围的entity字段层级(即模仿流控,熔断的实现方式)。
在dashboard的页面回显/传参等操作上也要处理。
3、实体id的持久化
在进行respository.save()方法时,会生成对应id,内存实现是维护了一个atomic,如果应用重启,会导致id丢失错乱的情况。
改造方法可以选择集中式持久化,比如db,redis等方式