高并发架构设计原则
高并发(拆分、服务化、消息队列、缓存)
高可用(集群、限流、降级)
业务设计(幂等、防重、状态机)
限流的目的
限流的目的是通过并发访问/请求进行限速或者一个时间窗口内的请求进行限速来保护系统的可用性,一旦达到限制速率就可以拒绝服务,是一种有损服务。
限制瞬时并发数
比如在入口层 nginx添加nginx_http_limit_conn_module来限制同一个IP来源的连接数,防止恶意攻击访问的情况
限制总并发数
通过配置数据库连接池、线程池大小来约束总并发数
限制时间窗口的平均速率
在接口层面,通过限制访问速率来控制接口的并发请求
其他方式
限制远程接口调用速率、限制MQ的消费速率
常见的限流算法
1、滑动窗口协议:
一种常见的流量控制技术,用来改善吞吐量的技术
2、漏桶
漏桶算法能强行限制数据传输速率
3、令牌桶
令牌桶属于控制速率类型的限流算法
4、计数器
最简单的一种,通过控制时间段内的请求次数
滑动窗口协议
滑动窗口(Sliding window)是一种流量控制技术,早期的网络通信中,通信双方不会考虑网络的拥挤情况直接发送数据。由于大家不知道网络拥塞情况,同时发送数据,会导致中间节点阻塞掉包,谁也发不了数据,所以就有了滑动窗口机制来解决此问题。
发送和接受方都会维护一个数据帧的序列,这个序列称作窗口。
发送窗口:
就是发送方允许连续发送的帧的序号表。
发送端可以不等待应答而连续发送的最大帧数称之为发送窗口的尺寸。
接收窗口:
接收方允许接收的帧的序号表,凡落在接收窗口内的帧,接收方都必须处理,落在接收窗口外的帧被丢弃。接收方每次允许接收的帧数称之为接收窗口的尺寸。
滑动窗口协议:
image.png演示效果如下:
image.png漏桶算法
控制传输速率
漏桶算法思路很简单,请求先进入到漏桶里,漏桶以一定的速度出水,当水请求过大会直接溢出,可以看出漏桶算法能强行限制数据的传输速率。
漏桶算法.png漏桶算法的核心为:存下请求、匀速处理、多于丢弃,是一种强行限制请求速率的方式,缺点非常明显,主要有两点:
1、无法面对突发的大流量---比如请求处理率为1000,容量为5000,来了一波2000/s的请求持续10s,那么后5s的请求将全部直接被丢弃,服务器拒绝服务,但是实际上网络中突发一波大流量尤其是短时间的大流量是很正常,这种超过容量就拒绝,是非常简单粗暴的。
2、无法有效利用网络资源---比如服务器的处理能力是1000/s,这个1000/s 只是一个宏观服务器处理能力的数字,假设5秒内,每秒请求量分别为1200、1300、1200、500、800,平均下来qps也是1000/s,但是这个量对服务器来说是完全可以接受的,但是因为限制了速率1000/s ,因此前面的三秒每秒只能处理1000个请求而一共打回了700个请求,白白浪费了服务器资源。
令牌桶算法
对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。
令牌桶算法.png假设我们想要的速率是1000QPS,那么往桶中放令牌的速度就是1000个/s,假设第1秒只有800个请求,那意味着第2秒就可以容许1200个请求。漏桶算法第一秒只有800个请求,那么全部放过,第二秒1200个请求,其中就有200个请求被打回。
令牌桶算法要特别注意设置桶中的令牌上限,假设还是1000个QPS,前5秒放1000个令牌,第一秒来了800个请求,第2-4秒没有请求,那么按照令牌桶算法,第5秒钟可以接受4200个请求,这样就超过了系统承载的能力。