-
Notifications
You must be signed in to change notification settings - Fork 8k
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
关于线程限流问题的讨论 #59
Comments
我同意这个issue。源码中确实会存在这种可能。DefaultProcessorSlotChain中首先会进行例如FlowSlot.entry的检查,然后才会在StatisticSlot.entry进行统计数量。如果不使用同步机制,有可能会同时几个线程同时调用DefaultProcessorSlotChain超过线程上限。 |
这里面不做同步的一个重要的原因,是一个性能的平衡.
如果我们在所有的检查中都加锁,会带来一个性能的骤降;所以我们选择了放弃处理这种极端情况.
如果有什么好的建议,也请告知我们。
Regards,
发件人: byamao1 [mailto:notifications@github.com]
发送时间: 2018年8月15日 13:59
收件人: alibaba/Sentinel <Sentinel@noreply.github.com>
抄送: Subscribed <subscribed@noreply.github.com>
主题: Re: [alibaba/Sentinel] 关于线程限流问题的讨论 (#59)
我同意这个issue。源码中确实会存在这种可能。DefaultProcessorSlotChain中首先会进行例如FlowSlot.entry的检查,然后才会在StatisticSlot.entry进行统计数量。如果不使用同步机制,有可能会同时几个线程同时调用DefaultProcessorSlotChain超过线程上限。
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub <#59 (comment)> , or mute the thread <https://github.com/notifications/unsubscribe-auth/AgQHwEniJJTkmmTnkR5lUO-aWw-cxf86ks5uQ7iTgaJpZM4V74Ec> . <https://github.com/notifications/beacon/AgQHwNZXXD0DTyG0TZUTXLmyvFBR-_IDks5uQ7iTgaJpZM4V74Ec.gif>
|
我对工程中的FlowThreadDemo进行了修改:
下步我会结合效率和限流能力,试图找到一个平衡点方案。(有苛刻之处乃本人之误,如需测试代码可联系本人) |
太好了!!
欢迎提一个PR!!!
发件人: byamao1 [mailto:notifications@github.com]
发送时间: 2018年8月15日 15:25
收件人: alibaba/Sentinel <Sentinel@noreply.github.com>
抄送: 林佳梁(子矜) <jialiang.linjl@taobao.com>; Comment <comment@noreply.github.com>
主题: Re: [alibaba/Sentinel] 关于线程限流问题的讨论 (#59)
我对工程中的FlowThreadDemo进行了修改:
* 开启10个线程群(1个群25个线程)进行饱和测试
* 加入CyclicBarrier保证线程群内能够同时触发SphU.entry
* 在log处改造为if(oneSecondPass > 20)
测试结果来看,限流能力与methodBRunningTime有正比比关系:methodBRunningTime越小,能力越小。
下步我会结合效率和限流能力,试图找到一个平衡点方案。(有苛刻之处乃本人之误,如需测试代码可联系本人)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub <#59 (comment)> , or mute the thread <https://github.com/notifications/unsubscribe-auth/AgQHwIREJbPuK8Hm_0fnrHrr3knVg7X7ks5uQ8yvgaJpZM4V74Ec> . <https://github.com/notifications/beacon/AgQHwGt2fII3L3u401OObTU2HoGfM_bOks5uQ8yvgaJpZM4V74Ec.gif>
|
如果有办法将线程限流的判断还有加减1放在一个地方(就可以会用信号量来做了),就可以规避这个问题,而且性能不会太差,但可能会违背了现有的操作链的设计方式,不妨尝试一下 |
用令牌的方式来限制资源被访问次数应该是可行的。与信号量差不多的思路(水平有限),只不过是利用原子类实现了令牌的个数限制。代码放在博客,有问题互相交流。 |
@byamao1 你这段代码也是有问题的,令牌桶其实很难实现并发控制的效果:https://blog.csdn.net/manzhizhen/article/details/81413014 |
@jialianglinjl @sczyh30 @byamao1 我想到一种方案,通过信号量+ThreadLocal来实现,我写完到时候各位看一下 |
好的!!
…------------------------------------------------------------------
发件人:yizhenqiang <notifications@github.com>
发送时间:2018年8月20日(星期一) 11:02
收件人:alibaba/Sentinel <Sentinel@noreply.github.com>
抄 送:林佳梁(子矜) <jialiang.linjl@taobao.com>; Mention <mention@noreply.github.com>
主 题:Re: [alibaba/Sentinel] 关于线程限流问题的讨论 (#59)
@jialianglinjl @sczyh30 @byamao1 我想到一种方案,通过信号量+ThreadLocal来实现,我写完到时候各位看一下
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
|
好的,方案看起来可待。 |
是否考虑用volatile 去定义线程数。相较于锁,它的性能不差。 |
volatile 只能保证可见性,不能保证变量递增递减操作的原子性。 |
感谢指正,我忽略了递增,递减并不是原子性操作,那我只能想到的也就是上面提到的信号量的方式,@byamao1 |
如果没有很好的方案,建议给两个策略: |
一开始以为做成责任链,可以让用户像netty pipeline一样自定义handler,每个slot都是独立的,现在slotChain里的flowSolt和systemSolt依赖StatisticSlot的统计信息,这个问题,是否考虑让slot维护自己的信号量,而不是依赖Node上的线程数. |
这么设计应该是有缘由的,需要coder澄清 |
@project620 @byamao1 感谢各位的讨论,不好意思现在才关注到各位的消息,确实,Sentinel责任链设计模式的应用让一个限流熔断系统的逻辑变得清晰,有迹可循,其实这次改动并不大,只是加强了线程限制的校验而已,原有功能和关联关系并没有发生变化(@project620 提到的FlowSolt是指?),原本SystemSolt中的实现也会依赖StatisticSlot的统计数据,否则限流无从下手的。具体可以参见这次改动: https://github.com/alibaba/Sentinel/pull/76/files 欢迎继续讨论!!! |
@manzhizhen @byamao1 @sczyh30 |
精确统计 和 高并发 两者应该不能同时兼顾。即使使用CAS也会因为对共享区的竞争而降低并发能力;使用LongAdder这样的高并发类就会牺牲精确性。 |
@manzhizhen 这个也不仅仅是性能的问题,还有在于责任的隔离,你的做法我个人理解是在统计的Slot里面把限流的逻辑也加进去了,不知道我想的有没有问题,可以讲解一下,如果我理解错了的话还希望能够指正。 |
@manzhizhen 我刚仔细看了下。。懂你的代码的意思了。你的代码实际上是用了一个全局的信号量去控制并发线程数,在StatisticSlot中获取到了限流结果,然后将限流结果和全局信号量引用放到了threadlocal里面,延迟到了systemRuleSlot中进行判断。功能上肯定没问题,不过就是看责任划分上,实际上已经做到了尽可能的划分了,不过如果要精确统计就无法做到责任的完全划分,这个就看作者和本身开发点的一个考虑了。对于并发线程这个场景你的方案应该覆盖到了。 |
@ro9er 一个比较好的设计是把统计信号量的结果作为统计数据的一部分保存在统计结果对象里面,然后向下传递,最后交给其他的Slot来使用,比如判断什么的。 |
private static void initFlowQpsRule() { public static void main(String[] args) {
public static void entry() { 如上文:设置了并发阈值为4,开启100个线程同时访问。结果都访问到资源,没有被限流
|
Issue Description
bug report
Describe what happened (or what feature you want)
sentinel采用类似于责任链的设计模式,将统计、限流、降级、监控等功能串起来,使每个环节自责更清晰(见DefaultSlotsChainBuilder),这种设计模式对于大多数关于“数量”的统计场景是没问题的,比如QPS、错误量等。但对于线程数限流(即并发限流)这样做是有问题的,详见:https://blog.csdn.net/manzhizhen/article/details/81413014。
在Sentinel中,当前服务对线程数加(请求进来)和减(请求执行完毕)的操作是在StatisticSlot中完成的:
而线程数的限流操作是在另一个类来做的,例如SystemSlot:
其中SystemRuleManager.checkSystem的操作如下:
public static void checkSystem(ResourceWrapper resourceWrapper) throws BlockException {
将统计和限流分开的这种方式,无法真正做到线程数量(也就是并发度)的精准控制,会有竞态条件产生,比较好的做法是用信号量来实现。
Describe what you expected to happen
How to reproduce it (as minimally and precisely as possible)
Tell us your environment
Anything else we need to know?
The text was updated successfully, but these errors were encountered: