在微服务中如何限流?在工作中是怎么做的?说一下具体的实现?

        限流可以认为服务降级的一种,限流就是限制系流的输入和输出流量,以达到保护系统的目的。一般来说,系统的吞吐量是可以被测算的。为了保证系统的稳定运行,一旦达到需要限制的阀值,就需要限制流量并采取一些措施以完成限制流量的目的,比如:延迟处理、拒绝处理、或者部分拒绝处理等。



(1)计数器算法。
        采用计数器实现限流有点简单粗暴,一般我们会限制一秒钟的能够通过的请求数,比如限流qps为100算法的实现思路就是从第一个请求进来开始计时,在接下去的 1s内,每来一个清求,就把计数加1。如果累加的数字达到了100,那么后续的请求就会被全部拒绝。等到1s 结束后,把计数器恢复为0,重新开始计数。
        具体实现可以是这样的:对于每次服务调用,可以通过AtomicLong #increamentAndGet()方法来给计数器加并返回最新值,通过这个最新值和阈值进行比较。

        这种实现方法有一个弊端:如果在单位时间1s内的首10ms已经通过了100个请求,那么后面990ms.只能请求拒绝。我们把这种现象称为“突刺现象”。


(2)漏桶算法
        为了消除“突刺现象”,可以采用漏桶算法实现限流。漏桶算法这个名字很形象,算法内部有一个容器,类似生活中用到的漏斗。当请求来时,相当于水倒入漏斗然后从下端小口慢慢匀速的流出,不管上面的流量多大,下面流出的速度终保持不变。
        不管服务调用方多么不稳定,通过漏桶算统这个进行很流,漏桶每10ms处理一次清求,因为处理的速度是固定的,请求进来的速度是未知的,可能突然进来很多请求,没来得及处理的请求,没来得及处理的请求就先放在桶里。既然是一个桶,肯定会有容量上限。如果桶满了,那么新进来的请求就丢弃。
        在算法实现方面,可以准备一个队列,用来保存请求。另外通过一个线程池从队列中获取请求并执行,可以一次性获取多个并发执行。这种算法也存在弊端:无法应对短时间的突发流量。



(3)令牌桶算法。
        从某种意义上讲,令牌桶算法是对漏桶算法的一种改进。桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。
        在令牌桶算法中。存在一个桶,用来在放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择等待可用的令牌,或者直接拒绝。
        放令牌这个动作是持续不断地进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况:桶中一直有大量的可用令牌,这时进来的清求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器就可以抵挡瞬时的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行。



(4)集群限流

        前面讨论的几种算法都属于单机限流的范畴,但是业务需求五花八门,简单的单机限流、根本无法满足他们。
        比如为了限制某个资源被用户或者商户的访问次数,5s内只能访问2次,或者1天只能调用 1000次。这种需求单机限流是无法实现的,这时就需要进行集群限流来实现。
        如何实现?为了控制访问次数肯定需要一个计数器面且这个计数器只能保存在第三方服务。如 redis大概思路:每次相关操作时,就向redis服务器发送一个incr命令,比如需要限制某个用户访问/index接口的次数,只需要拼接用户id和接口名生成redis的key。每次该用户访问此接口时,只需要对这个key现行incr命令,在这个key带上过期时间,就可以实现指定时间的访问频率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值