Sentinel限流熔断—解决限流/XXXX/{id}查询接口不准确的问题
问题分析
Sentinel中HTTP服务的限流默认由Sentinel-Web-Servlet包中的CommonFilter来实现,从代码中可以看到,这个Filter会把每个不同的URL都作为不同的资源来处理。
在下面这段代码中,提供了一个携带{id}参数的REST风格API,对于每一个不同的{id},URL也都不一样,所以在默认情况下Sentinel会把所有的URL当做资源来进行流控。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@GetMapping("/product/{id}")
public String getProductById(int id){
return "hhhhh product ";
}
}
这会导致两个问题:
1、限流统计不准确,实际需求是控制getProductById方法总的QPS,结果统计的是每个URL的QPS;
2、导致Sentinel中资源数量过多,默认资源数量的阈值是6000,对于多出的资源规则将不会生效。
针对这个问题可以通过UrlCleaner接口来实现资源清洗,也就是对于/product/{id}这个URL,我们可以统一归集到/product/*资源下,具体配置代码如下,实现UrlCleaner接口,并重写clean方法即可。
package xxx;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.UrlCleaner;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
@Component
public class CustomUrlCleaner implements UrlCleaner {
@Override
public String clean(String originUrl) {
if(StringUtils.isBlank(originUrl)){
return originUrl;
}
if(originUrl.startsWith("/product/")){
return "/product/*";
}
return originUrl;
}
}