服务器端限流保护

之前开发一个视频聊天室服务,碰到许多服务器端高并发性能的问题,所以进行了一些这方面的学习。服务器端在收到客户端过多的请求时,往往会因为过高的cpu或者内存消耗而宕掉。这就有一个原则是服务端要能自我保护,宁可提供受损的服务,也不能不提供服务。在开发高并发系统时有三把利器来保护系统:缓存降级限流

缓存的目的是提升系统访问速度和增大系统能处理的容量。项目中有很多地方用到了缓存。其中一个场景是,客户端会上传一个信令表明身份,而这个信令有专门的服务来维护,我们就需要拿着这个信令调用那个服务的http接口来验证,当并发较多时,http请求就有可能拥堵。考虑到这个信令的存活时间较长,就可以在redis中做一下缓存,定期清理。这样就减少了http请求次数。

降级是当服务出问题或者影响到核心流程的性能时,需要暂时屏蔽掉一些服务,待高峰或者问题解决后再打开。这个方法基本上每一个服务都用到了,高峰时或者cpu、内存占用较高时,减少日志记录、主动拒绝一些请求等等。

限流的目的是通过对并发访问/请求进行限制或者一个时间窗口内的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务或者排队等待。

令牌桶算法

令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。简单描述如下:

  • 假设限制2r/s,则按照500ms的固定速率往桶中添加令牌;
  • 同种最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝;
  • 当n个请求到来时,从同种删除n个令牌,接着处理请求;
  • 如果桶中的令牌不足n个,则拒绝后面的部分

令牌桶

漏桶算法

漏桶作为计量工具时,可以用于流量整形和流量控制。简单描述如下:

  • 一个固定容量的漏桶,按照常量固定速率流出水滴;
  • 如果桶是空的,则不需要流出水滴;
  • 可以以任意的速率流入水滴;
  • 如果流入水滴超出了桶的容量,则流入的水滴溢出,被丢弃。

漏桶

对比这两个算法

  • 令牌桶是按照固定速率往桶中添加令牌,请求是否被处理需要看桶里令牌是否足够,当令牌数是零时拒绝新的请求。
  • 漏桶是按照常量固定速率流出请求,流入请求速率任意,当流入的请求数量累计到漏桶容量时,则新流入的请求被拒绝。
  • 令牌桶限制的是单位时间内的平均流入速率,但是允许突发请求
  • 漏桶限制的是流出速度,也就是处理速度,碰到突发请求,也是按固定速率处理这些请求,平滑突发流入速率

我们这次优化只用到了漏桶算法。其实实现很简单,就是用到一个队列。队列的一端不断添加请求,另一端按照固定的速率,例如每秒1个,来从队列中读取请求处理。如果队列满了,可以选择一种策略来处理新来的请求,一是直接丢弃新请求,二是覆盖旧的请求。这个队列也可以改为用栈来实现,具体情况具体分析。

计数器限流

主要用来限制总并发数,对全局总请求数或者单位时间内的总请求数进行限流。这个方法比较简单。

应用级限流

  • 限制总并发/连接/请求数。例如Tomcat、Nginx、Redis可以对线程数、连接数做限制。
  • 限制总资源数。如果有的资源是稀缺自然,而且可能有多个系统都会使用它,那么需要限制应用。最常用的是池化技术,线程池或者连接池。
  • 限流某个接口的总并发/请求数。在Java中可以用AtomicLong进行计数限制。
  • 限流某个接口的时间窗请求数。这和上面的相似,可以用一个计数器进行限制。
  • 平滑限流某个接口的请求数。上面的两种方法都不能很好的应对突发请求,但有时候会需要对突发请求做一些平滑整形。这时候可以用令牌桶或者漏桶算法。

分布式限流

分布式限流最关键的是讲限流服务做成原子化,而解决方案可以使用redis+lua或者nginx+lua。我对nginx不熟,而且redis性能很好,所以偏向于使用redis。

local key = KEYS[1] --限流KEY(一秒一个)
local limit = tonumber(ARGV[1])        --限流大小
local current = tonumber(redis.call('get', key) or "0")
if current + 1 > limit then --如果超出限流大小
   return 0
else if current == 1 then --设置2秒过期
    redis.call("INCRBY", key, "1")
    redis.call("EXPIRE", key, "2")
else  --请求数+1
   redis.call("INCRBY", key,"1")
   return 1
end
参考

转载于:https://www.cnblogs.com/xianzhedeyu/p/5868024.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值