Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can servlet filter(CommonFilter) support ParamFlow? #2014

Open
furaul opened this issue Feb 4, 2021 · 4 comments
Open

Can servlet filter(CommonFilter) support ParamFlow? #2014

furaul opened this issue Feb 4, 2021 · 4 comments
Labels
area/hotspot-param-flow Issues or PRs related to "hot-spot" param flow control kind/discussion For further discussion kind/feature Category issues or prs related to feature request.

Comments

@furaul
Copy link

furaul commented Feb 4, 2021

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)

  1. 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."; }
  2. 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 } ]
  3. Send a request '/param'
    发送’param‘的http请求
  4. The result is that the param flow rule is not activated.
    结果是热点参数限流规则没有生效。
  5. 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方法时,没有传入参数列表。
  6. 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.

@cdfive
Copy link
Collaborator

cdfive commented Feb 5, 2021

是的,原因是CommonFilter这个类调用SphU#entry方法时,没有传入参数列表

目前sentinel-web-servletsentinel-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设置普通流控规则就好。
因为热点商品是单独的资源了,也可设置其它规则,比如降级规则。

@paoyingshidai
Copy link

我对这个问题的看法是:对于 SphU#entry 方法的调用是否可以用 protected 方法取代,在 AbstractSentinelInterceptor 中实现默认的方法,使其子类可以覆盖这个默认方法,在这个 protected 中传入 interceptor 的 pre 方法的入参,这样子类决定怎么处理参数和怎么调用 SphU#entry,我是准备在项目中重写 AbstractSentinelInterceptor 这个类。

@jasonjoo2010
Copy link
Collaborator

这个建议是直接fork出springmvc的adapter进行自定义来实现(改为自己的package),或者使用注解方式针对某几个方法来启用热点相关的流控。

因为参数多样,且影响一定性能,这个可能较难作为通用需求(filter模式)

@furaul
Copy link
Author

furaul commented Mar 16, 2021

是的,原因是CommonFilter这个类调用SphU#entry方法时,没有传入参数列表

目前sentinel-web-servletsentinel-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设置普通流控规则就好。
因为热点商品是单独的资源了,也可设置其它规则,比如降级规则。

我觉得这只需要支持常用的一两种就可以,比如支持get/post,就已经满足90%的场景了。
其他的场景开放扩展给使用者自己实现转换即可。

@sczyh30 sczyh30 added kind/discussion For further discussion kind/feature Category issues or prs related to feature request. labels Mar 25, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/hotspot-param-flow Issues or PRs related to "hot-spot" param flow control kind/discussion For further discussion kind/feature Category issues or prs related to feature request.
Projects
None yet
Development

No branches or pull requests

5 participants