在高并发系统中,流量控制非常重要。当直接向我们的服务器请求大流量时,可能用不了多久就会出现接口不可用的情况。如果不处理,甚至会导致整个应用不可用。比如最近有这样一个需求。作为客户端,我要生产数据给Kafka,Kafka消费者不断消费数据,把消费的数据全部请求给web服务器。虽然负载很大(有4台web服务器),但是业务数据量也很大,每秒钟可能产生几万条数据。如果生产者直接生产数据,很有可能拖垮web服务器。为此,需要做限流处理,每秒钟产生一定量的数据给Kafka,这样才能在很大程度上保证web的正常运行。其实不管处理什么样的场景,本质都是降低流量,保证应用的高可用。常用算法常用的限流算法有两种:漏桶算法令牌桶算法漏桶算法比较简单,就是将流量放入桶中,漏桶也按照一定的速率流出。如果流量太快,就会溢出(漏桶不会增加流量)。溢出的流量直接丢弃。如下图所示:这种做法简单粗暴。漏桶算法虽然简单,但无法应对实际场景,比如流量突然激增。这时候就需要用到令牌桶算法:令牌桶会以恒定的速率往固定容量的桶中放入令牌,当有流量时取走一个或多个令牌。当桶中没有令牌时,当前请求被丢弃或阻塞。相比之下,令牌桶可以处理一定的突发流量。RateLimiter实现对于令牌桶的代码实现,可以直接使用Guava包中的RateLimiter。调用结果如下:代码可以看到每秒有两个token放入桶中,请求一次消耗一个token。所以每秒只能发送两个请求。按照图中的时间是这样的(返回值是获取这个token的时间,差不多是500ms一次)。使用它有几点需要注意:允许先消费,后支付,也就是说它可以一次性拿走剩余的几个或全部token,甚至有请求来的时候拿走更多,但是后面的请求必须是上次请求买单时,需要等待桶中的代币填满后才能继续获取代币。总结限制单个应用程序的电流就足够了。如果是分布式环境,可以借助Redis来完成。
