Issue Description
Type: feature request
Describe what happened (or what feature you want)
Can servlet filter support ParamFlow?
Servlet filter模式的限流(com.alibaba.csp.sentinel.adapter.servlet.CommonFilter)可以支持热点参数限流吗?
Describe what you expected to happen
ParamFlow is supported in servlet filter mode.
热点参数限流可以在servlet限流模式中被支持。
How to reproduce it (as minimally and precisely as possible)
- Define a GET method by springMVC
使用springMVC定义一个GET方法@GetMapping("param") public String testParam(Integer param) { LOGGER.info("Dubbo request succeed. param is [{}]", param); return "Dubbo request succeed."; }
- Configure a param flow rule
如下所示,配置一条热点参数限流规则[ { "resource": "/param", "limitApp": "default", "grade": 1, "paramIdx": 0, "count": 1, "controlBehavior": 0, "maxQueueingTimeMs": 0, "burstCount": 0, "durationInSec": 1, "paramFlowItemList": [ { "object": "1", "count": 2, "classType": "int" } ], "clusterMode": false } ]
- Send a request '/param'
发送’param‘的http请求 - The result is that the param flow rule is not activated.
结果是热点参数限流规则没有生效。 - I found out the reason is that the com.alibaba.csp.sentinel.adapter.servlet.CommonFilter does not carry the arguments when it invoke com.alibaba.csp.sentinel.SphU#entry(java.lang.String, int, com.alibaba.csp.sentinel.EntryType)。
初步分析,原因是CommonFilter这个类调用SphU#entry方法时,没有传入参数列表。 - If I define the get method like this , the param rule will be activated, because com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect carries the arguments.
如果使用@SentinelResource来做资源定义,热点参数限流规则可以生效。
’
@SentinelResource(value = "/param")
public String testParam(Integer param) {
LOGGER.info("Dubbo request succeed. param is [{}]", param);
return "Dubbo request succeed.";
}
‘
Tell us your environment
mac,sentinel-1.8.0
Anything else we need to know?
No more.
4条答案
按热度按时间tgabmvqs1#
是的,原因是
CommonFilter这个类调用SphU#entry方法时,没有传入参数列表
。目前
sentinel-web-servlet
和sentinel-spring-webmvc-adapter
均不支持热点参数限流。可能原因是,对于http request请求,不同项目可能获取参数的方式不一样。比如:
有的是get请求,参数在url里;
有的是post请求,参数在body里;
有的参数是form data形式;
有的参数是json格式;
有的参数就一个,比如body里有个data参数,data里面是具体的json格式参数;
有的不区分get/post;
SphU#entry
方法最后1个参数是Object[] args
,可用于支持热点参数限流。理论上说,如果项目的请求参数格式统一,应该可以按某个标准统一获取参数,最后转换为
Object[] args
形式。有什么好的建议吗?大家一起讨论下 @furaul@jasonjoo2010@sczyh30
PS:
sentinel-web-servlet
模块提供了UrlCleaner
扩展,参考:https://github.com/alibaba/Sentinel/wiki/主流框架的适配#web-servlet
它可用于清洗或者过滤资源(比如将满足 /foo/:id 的 URL 都归到 /foo/* 资源下,比如通过返回""排除某个URL)
如果换个思路,基于它扩展也可实现热点参数限流。比如想对某个热点商品限流,实现一个自定义的
UrlCleaner
接口,里面获取到热点商品id参数,返回带上商品id的特定URL,这样生成新的资源,结合控制台就可以单独设置该URL的限流规则。
如:普通商品详情页的URL为:/product/detail,热点商品详情页URL为:/product/detail?id=xxx
然后对两个URL设置普通流控规则就好。
因为热点商品是单独的资源了,也可设置其它规则,比如降级规则。
zengzsys2#
我对这个问题的看法是:对于 SphU#entry 方法的调用是否可以用 protected 方法取代,在 AbstractSentinelInterceptor 中实现默认的方法,使其子类可以覆盖这个默认方法,在这个 protected 中传入 interceptor 的 pre 方法的入参,这样子类决定怎么处理参数和怎么调用 SphU#entry,我是准备在项目中重写 AbstractSentinelInterceptor 这个类。
2fjabf4q3#
这个建议是直接fork出springmvc的adapter进行自定义来实现(改为自己的package),或者使用注解方式针对某几个方法来启用热点相关的流控。
因为参数多样,且影响一定性能,这个可能较难作为通用需求(filter模式)
hl0ma9xz4#
我觉得这只需要支持常用的一两种就可以,比如支持get/post,就已经满足90%的场景了。
其他的场景开放扩展给使用者自己实现转换即可。