sentinel

redis+lua限流

2019-10-25  本文已影响0人  lesline

nginx+lua(openresty/kong)

Lua 是一种轻量小巧的脚本语言,动态解释型语言 ,一个完整的Lua解释器不过200k,在目前所有脚本引擎中,Lua的速度是最快的。这一切都决定了Lua是作为嵌入式脚本的最佳选择。
主要特点是:程序代码级热更新,下载最新代码,实时更新,实时更新,不需要编译环节,比如Nginx

1: 比如游戏引擎领域的cocos2d-x、unity,由于引擎自身使用的c++或者c#作为编写语言,游戏前端发布后,发现bug或者发布新逻辑,都需要重新出包,周期过长,lua作为脚本语言,可以以资源的形式下载,重新加载运行,周期快,且效率损失有限
2:服务端使用,比较火的也就是nginx+lua的形式,后来整合成框架openresty,基本也是利用nginx的高性能+lua脚本的灵活性,逻辑修改之后只需要触发重新加载脚本就可以,开发运行效率都比较高,相比传统c++、java等需要重新编译部署,开发效率高很多

京东实现

  1. 有一个定时任务10秒更新限流配置(黑白名单和限流开关)
    local ok, err = new_timer(delay, refresh)
  2. 主要逻辑
-- 规则设置
-- 排队规则,即并发数控制+防刷规则,即请求频率控制(集群TPS,用户TPS,单IP的TPS[取不到用户的时候才生效])
-- AddOn:当前代码无法校验TrackID合法性,故全部使用IP限流,请注意第三个数字!!!(忽略第二个)
global_key_rules = {
  ['/cart/add_to_cart_ajax.html'] = {1000, -1, 50},
  ['/cart/fetch_cart_num.html'] = {1000, -1, 50},
  ['/cart/sync_cart.html'] = {500, -1, 30},
  ['/order/confirm_order.html'] = {500, -1, 30},
  ['/order/sync_order_cart.html'] = {500, -1, 30},
  ['/order/edit_user_address.html'] = {300, -1, 20},
  ['/order/sync_user_coupon.html'] = {500, -1, 30},
  ['/order/submit_order.html'] = {200, -1, 20}
}
-- 主要判断逻辑 
-- key 为限制的资源
-- size 为TPS值
function limit(red, key, size)
    --访问量+1
    local count = red:incr(key)
    -- 判断是否过期,如果过期,修改过期时间为1秒,ttl返回剩余的生存时间,key不
    local ttl = red:ttl(key)
    if ttl < 0 then
      local time = red:expire(key,1)
    end
    -- 判断超过TPS,超过则限流
    if count > size  then
       return false
    end
    return true
 end

ttl是为防止某些key在未设置超时时间并长时间已经存在的情况下做的保护的判断;

Redis TTL 命令:
当 key 不存在时,返回 -2 。
当 key 存在但没有设置剩余生存时间时,返回 -1 。
否则,以毫秒为单位,返回 key 的剩余生存时间。

Redis Incr 命令:
将 key 中储存的数字值增一。
如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作

通过redis防止重复提交(无并发限流)

通过redis也可以在服务层做限流,缺点是此时流量已打到服务器,没有在nginx层做防护好。
不过,可以在服务层做些防重复提交的防护,示例如下:
例如:PC端查询订单列表,同一用户和相同查询条件100毫秒内只能查询一次

通过Redis 字符串命令SETEX key seconds value实现
setex 惟一标识 过期时间 当前时间
其中:key:为资源惟一标识=uid+param
seconds:过期时间=repeat_request_ttl
valule:当前时间

repeat_request_ttl: 每次查询的时间间隔=100
表示:同一用户和相同查询条件100毫秒内只参查询一次

if(key 存在){
  获取key值的value=上次请求时间
  if(上次请求时间<repeat_request_ttl){
     请求频率过快
   }
}
set key 当前时间 过期时间
上一篇下一篇

猜你喜欢

热点阅读