技术问答集录(五)(服务端全局限流和客户端Mock)

如何让开发无需编码实现服务端全局限流和客户端Mock两大功能?

限流

1.1 限流是在遇到流量高峰期、流量突增时,把流量速率限制在系统所能接受的合理范围内,防止系统被高流量击垮。

1.2常用限流算法

限流方案很多,每种方案都有自己的限流算法、适用的场景。整理了如下几种常用的限流算法。

1.2.1 固定窗口计数器

在每个计时窗口内,每有1次请求,计数器加1;如果计数器超过了限制数量,则本窗口内所有的请求都被丢弃;当时间到达下1个计时窗口时,计数器被重置。

优点:算法实现简单。

缺点:这个算法可能会让通过的请求量翻倍。比如,限制1秒内最多通过10个请求,在第一个计时窗口的后半秒通过10个请求,下一个窗口的前半秒通过10个请求,这样1秒内则通过了20个请求。

1.2.2 滑动窗口计数器

比如服务每秒最多处理10个请求,设置一个1秒钟的滑动窗口,窗口中有10个格子,每格为100毫秒,记录请求数;每100毫秒移动一次,抛弃最老的格子,增加一个新格,如果当前窗口内的请求总数超过了限制,则抛弃请求。

优点:避免了固定窗口计数器的请求翻倍。

缺点:时间划分的区间精度越高,算法所需的空间容量就越大。

1.2.3 漏桶

漏桶算法多使用队列实现,服务请求存储到队列中,服务提供方则按照固定的速率从队列中取出请求并执行,过多的请求则放在队列中排队或直接拒绝。

Nginx接入层限流的ngx_http_limit_req_module模块,是基于漏桶算法实现。

优点:平滑了突发流量。

缺点:当短时间内有大量请求时,即便此时服务负载很低,每个请求也要在队列中等待一段时间才能被响应。

1.2.4 令牌桶

生成的令牌以固定速率放入令牌桶中,如果令牌桶满了则多余的令牌会直接丢弃;当请求到达时,尝试从令牌桶中获取令牌,如果取到令牌则请求执行,如果桶空了,那么尝试取令牌的请求会被抛弃。

优点:能够限制请求的平均速率,还允许某种程度的突发流量;可以方便的改变请求速率,当需要提高速率时,则按需提高放入桶中令牌的速率。

缺点:容易导致误判。

此外还有其他利用redis存储计数和计时实现分布式限流方式

无需开发的方式目前通过Nginx接入层限流比较符合

使用网关方案

Spring Cloud的Zuul网关可以实现这样的方案。其底层使用ribbon来实现请求的路由,并内置Hystrix,可选择性提供网关fallback逻辑。 

Zuul中提供了过滤器定义,可以用来过滤代理请求。有前置过滤、路由后过滤、后置过滤、异常过滤等方式。  需要实现父类是ZuulFilter的过滤器。  

Zuul网关组件也提供了限流保护。当请求并发达到阀值,自动触发限流保护,返回错误结果。只要提供error错误处理机制即可。 

当请求通过zuul网关路由到服务,并等待服务返回响应,这个过程中zuul也有超时控制。zuul的底层使用的是Hystrix+ribbon来实现请求路由。结构如下:

参考 https://zhuanlan.zhihu.com/p/163074058

zuul中的Hystrix内部使用线程池隔离机制提供请求路由实现,其默认的超时时长为1000毫秒。ribbon底层默认超时时长为5000毫秒。如果Hystrix超时,直接返回超时异常。如果ribbon超时,同时Hystrix未超时,ribbon会自动进行服务集群轮询重试,直到Hystrix超时为止。如果Hystrix超时时长小于ribbon超时时长,ribbon不会进行服务集群轮询重试。

客户端mock

无需开发实现客户端mock功能,常见可以使用类似Eolinker,落兵台等mock平台编写api文档设置mock规则发布即可实现接口mock能力

同样用Zuul可以实现,用过滤器在路由后根据配置,可以将流量转发给模拟器,由模拟器返回响应结果

原文地址:https://www.cnblogs.com/fanBlog/p/13618799.html