文章目錄

太长不看版,开源的node-rate-limiter-flexible插件可以用作Node服务限流,非常好用。

最近把之前提供给业务方使用的Node服务对接到公司的中台服务,用上了服务限流,真的很香。本以为像我这样的非主流程序员一辈子都不会用上服务限流,没想到现在就用上了。

这个Node服务之前是通过运维提供的Nginx转发给业务方使用, 没有提供限流功能。一旦调用方的并发提高很多,导致负载过高,调用方会因为等待时间过长,导致调用超时。而健康检测也一样调用超时,只要有一个节点健康检测失败,就将流量打向其它的节点,其它节点流量就变高,之后调用超时,健康检测失败,又将流量打向其它节点,整个服务直接雪崩。

换成中台envoy服务转发后,就没有超时了,QPS也提高了,莫名其妙,运维也不给你机会找出原因,就此作罢。用中台的服务时,配置限流是用的令牌桶算法,提供了3个参数给你配置,最大桶数量,生成桶时间间隔,每次间隔生成桶数量。其实就是令牌桶算法,就是配置最大令牌桶和令牌生成速率,其中最大令牌桶用来支持突发流量。看了下令牌桶算法,就知道是怎么一回事了。假设QPS是300,超时时间5s,那么设置的最大令牌桶可以是1500,超过1500,有一些请求就会超时了,就这么简单。在测试环境测试后,看这限流生效了,就配置正式环境服务限流。

一切都还好,知道有一天,我发现请求的QPS超过了我设置的QPS,并且都请求成功了,也就是限流没有成功,于是找到中台服务提供方,那他们给个解释。折腾老半天后,才发现,中台的envoy服务没有做服务端限流,只做了客户端限流,服务端限流不知道啥时候才会安排。而我之前在测试环境的测试,只是在客户端限流。这就真的离谱,哪里有限流不做服务端限流的,真的离谱到家了。

于是又想用运维提供的Nginx做限流,让运维增加限流配置,测试了一圈发现提供的Nginx配置是针对客户端的IP限流,不是我想要的服务端限流,而因为之前运维的Nginx转发老是导致我的服务不可用,所以心理上也不太想用他们提供的转发,于是只好自己实现服务端限流。要实现整体服务限流,需要引入redis之类了额外服务,所以只想在每个服务节点内部实现限流。因为是Node程序,开源的node-rate-limiter-flexible插件就可以用来实现这个功能,其中BurstyRateLimiter支持突发流量,于是用它。它是用了两个限流配置,第一个的令牌用完了,就会去用第二个的。如下就是一个QPS是4,支持突发流量到8的配置,相当好用。第一个配置每一秒生成3个令牌,第二个配置每5秒生成5个令牌,那么5秒内就一共可以生成3 * 5 + 5 = 20个令牌,相当于这5秒内的QPS是4,而它的突发流量是8,也就是第一秒内如果进来8个请求,它也不会触发限流。

1
2
3
4
5
6
7
8
9
10
11
const burstyLimiter = new BurstyRateLimiter(
new RateLimiterMemory({
points: 3,
duration: 1,
}),
new RateLimiterMemory({
keyPrefix: 'burst',
points: 5,
duration: 5,
})
);

打赏作者

文章目錄