- [x] I have searched the [issues](https://github.com/apache/incubator-dubbo/issues) of this repository and believe that this is not a duplicate. - [x] I have checked the [FAQ](https://github.com/apache/incubator-dubbo/blob/master/FAQ.md) of this repository and believe that this is not a duplicate.
### Environment * Dubbo version: 2.6.3 ### Step to reproduce this issue 1. 配置限流过滤器; 2. 运行时修改系统时间; 3. 时间差范围内的正常请求全部被拒; ### 原因描述 过滤器[org.apache.dubbo.rpc.filter.TpsLimitFilter](https://github.com/apache/incubator-dubbo/blob/master/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TpsLimitFilter.java) 通过调用 [org.apache.dubbo.rpc.filter.tps.StatItem](https://github.com/apache/incubator-dubbo/blob/master/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/tps/StatItem.java)实现TPS限流。类org.apache.dubbo.rpc.filter.tps.StatItem实现了令牌桶算法, https://github.com/apache/incubator-dubbo/blob/f720ccb965d490e6cc328af8d3e9820cb6eaf8f7/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/tps/StatItem.java#L41-L56 上面的实现通过原子计数器token来记录可用令牌数量,在能取到令牌的情况下,每次调用对令牌数的自减。令牌桶重置(重新设置为最大值)的条件:**_当前系统时间 > 上次重置令牌的时间 + 时间间隔_**。 该实现对系统时间具有依赖性: 以`rate`=5000,`interval`=1000ms(即限流5000TPS),实际访问量为1000TPS为例,应用原来的时钟与标准时间同步,在系统运行过程中系统时钟发生了变化(可能因为应用服务器同步了错误的NTP服务导致): - 当系统时钟比标准时间慢(假设慢15分钟),则从差错时间点开始,当前系统时间重新变回到了15分钟前,而上次令牌重置时间并不会马上发生变化,导致`lastResetTime - now = 15min`,此时条件`now > lastResetTime + interval` 在接下来的15分钟之内不再不满足。意味着5000个令牌在1000TPS的实际访问量情况下5秒钟即被用完。后续的14分钟55秒的时间段内,所有的请求由于触发了限流的条件全部被拒,直到这个时间之后满足令牌桶重置的条件,才能恢复业务。 - 当系统时间比标准时间快(假设快15分钟),由于此时满足令牌桶重置的条件,限流可以正常工作。但是,在系统时间恢复至标准时间时,lastResetTime会比标准时间提前约15分钟,这时同样会导致系统时间恢复的15分钟后续的请求全部被拒绝,直到15钟后满足令牌通重置的条件。 ### Expected Result 在运行时系统时间发生变化,限流仍能正常发挥作用。 ### Actual Result 运行过程中系统时间发生变化,导致限流不能正确执行,后续请求在相差的时间长度范围,请求全部被拒绝。 [ Full content available at: https://github.com/apache/incubator-dubbo/issues/2345 ] This message was relayed via gitbox.apache.org for [email protected]
