OpenResty从入门到实战
温铭
OpenResty软件基金会主席,《OpenResty 最佳实践》作者
立即订阅
4332 人已学习
课程目录
已完结 52 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | OpenResty,为你打开高性能开发的大门
免费
入门篇 (14讲)
01 | 初探OpenResty的三大特性
02 | 如何写出你的“hello world”?
03 | 揪出隐藏在背后的那些子项目
04 | 如何管理第三方包?从包管理工具luarocks和opm说起
05 | [视频]opm项目导读
06 | OpenResty 中用到的 NGINX 知识
07 | 带你快速上手 Lua
08 | LuaJIT分支和标准Lua有什么不同?
09 | 为什么 lua-resty-core 性能更高一些?
10 | JIT编译器的死穴:为什么要避免使用 NYI ?
11 | 剖析Lua唯一的数据结构table和metatable特性
12 | 高手秘诀:识别Lua的独有概念和坑
13 | [视频]实战:基于FFI实现的lua-resty-lrucache
14 | 答疑(一):Lua 规则和 NGINX 配置文件产生冲突怎么办?
API篇 (11讲)
15 | OpenResty 和别的开发平台有什么不同?
16 | 秒杀大多数开发问题的两个利器:文档和测试案例
17 | 为什么能成为更好的Web服务器?动态处理请求和响应是关键
18 | worker间的通信法宝:最重要的数据结构之shared dict
19 | OpenResty 的核心和精髓:cosocket
20 | 超越 Web 服务器:特权进程和定时任务
21 | 带你玩转时间、正则表达式等常用API
22 | [视频]从一个安全漏洞说起,探寻API性能和安全的平衡
23 | [视频]导读lua-resty-requests:优秀的lua-resty-*是如何编写的?
24 | 实战:处理四层流量,实现Memcached Server
25 | 答疑(二):特权进程的权限到底是什么?
测试篇 (5讲)
26 | 代码贡献者的拦路虎:test::nginx 简介
27 | test::nginx 包罗万象的测试方法
28 | test::nginx 还可以这样用?
29 | 最容易失准的性能测试?你需要压测工具界的“悍马”wrk
30 | 答疑(三)如何搭建测试的网络结构?
性能优化篇 (16讲)
31 | 性能下降10倍的真凶:阻塞函数
32 | 让人又恨又爱的字符串操作
33 | 性能提升10倍的秘诀:必须用好 table
34 | 特别放送:OpenResty编码指南
35 | [视频]实际项目中的性能优化:ingress-nginx中的几个PR解读
36 | 盘点OpenResty的各种调试手段
37 | systemtap-toolkit和stapxx:如何用数据搞定“疑难杂症”?
38 | [视频]巧用wrk和火焰图,科学定位性能瓶颈
39 | 高性能的关键:shared dict 缓存和 lru 缓存
40 | 缓存与风暴并存,谁说缓存风暴不可避免?
41 | lua-resty-* 封装,让你远离多级缓存之痛
42 | 如何应对突发流量:漏桶和令牌桶的概念
43 | 灵活实现动态限流限速,其实没有那么难
44 | OpenResty 的杀手锏:动态
45 | 不得不提的能力外延:OpenResty常用的第三方库
46 | 答疑(四):共享字典的缓存是必须的吗?
API网关篇 (4讲)
47 | 微服务API网关搭建三步曲(一)
48 | 微服务API网关搭建三步曲(二)
49 | 微服务API网关搭建三步曲(三)
50 | 答疑(五):如何在工作中引入 OpenResty?
结束语 (1讲)
结束语 | 行百里者半九十
OpenResty从入门到实战
登录|注册

43 | 灵活实现动态限流限速,其实没有那么难

温铭 2019-09-02
你好,我是温铭。
前面的课程中,我为你介绍了漏桶和令牌桶算法,它们都是应对突发流量的常用手段。同时,我们也学习了如何通过 Nginx 配置文件的方式,来实现对请求的限流限速。不过很显然,使用 Nginx 配置文件的方式,仅仅停留在可用的层面,距离好用还是有不小的距离的。
第一个问题便是,限速的 key 被限制在 Nginx 的变量范围内,不能灵活地设置。比如,根据不同的省份和不同的客户端渠道,来设置不同的限速阈值,这种常见的需求用 Nginx 就没有办法实现。
另外一个更大的问题是,不能动态地调整速率,每次修改都需要重载 Nginx 服务,这一点我们在上节课的最后也提到过。这样一来,根据不同的时间段限速这种需求,就只能通过外置的脚本来蹩脚地实现了。
要知道,技术是为业务服务的,同时,业务也在驱动着技术的进步。在 Nginx 诞生的时代,并没有什么动态调整配置的需求,更多的是反向代理、负载均衡、低内存占用等类似的需求,在驱动着 Nginx 的成长。在技术的架构和实现上,并没有人能够预料到,在移动互联网、IoT、微服务等场景下,对于动态和精细控制的需求会大量爆发。
而 OpenResty 使用 Lua 脚本的方式,恰好能够弥补 Nginx 在这方面的缺失,形成了有效的互补。这也是 OpenResty 被广泛地用于替换 Nginx 的根源所在。在后面几节课中,我会为你继续介绍更多 OpenResty 中动态的场景和示例。今天,就让我们先来看下,如何使用 OpenResty 来实现动态限流和限速。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《OpenResty从入门到实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(5)

  • wusiration
    老师,限制器的组合小节里面的代码,limit_req重复了,应该有一个limit_count。
    课后习题:
    local limit_rate = require "resty.limit.rate"
    local limit_count = require "resty.limit.count"
    local limit_conn = require "resty.limit.conn"

    local lim_rate, err = limit_rate.new("my_rate_store", 100, 6000, 2) -- 将resty.limit.req替换成resty.limit.rate即可
    local lim_count, err = limit_count.new("my_count_store", 200, 100)
    local lim_conn, err = limit_conn.new("my_conn_store", 1000, 1000, 0.5)

    local limiters = {lim_rate, lim_count, lim_conn}
    local host = ngx.var.host
    local client = ngx.var.binary_remote_addr
    local keys = {host, client, client}

    local delay, err = limit_traffic.combine(limiters, keys, states)

    作者回复: 多谢指正,看的真仔细👍

    2019-09-02
    1
  • 文艺败类
    老师,我想要将限速限流参数放置在memcached中,每次请求时通过读取相关的配置来达到动态配置限流限速的功能(代码如下),当我扩大memcached中limit_num值后,发现返回的剩余的调用次数(remaining)并未发生变化,其中原理并不清楚,期望老师解惑或者提供更好的动态修改限流配置的方向

    local memcached = require "resty.memcached"
    local memc, err = memcached:new()
    memc:set_timeout(1000)
    local ok, err = memc:connect("127.0.0.1", 11211)
    local limit_num, flags, err = memc:get("limit_num")
    local limit_time, flags, err = memc:get("limit_time")

    local limit_count = require "resty.limit.count"
    local lim, err = limit_count.new("global_count_limit", tonumber(limit_num), tonumber(limit_time))
    local delay, remaining = lim:incoming('global', true)
    if not delay then
        return ngx.exit(503)
    end
    ngx.say(remaining)
    2019-11-10
    1
  • Sir
    老师好,我把这段代码也在location中,是不是相当于我每次请求都new了一次,比较迷惑
    local lim, err = limit_req.new("my_limit_req_store", 200, 100)

    作者回复: 这种对象的 new 一般都是放在 module 的 top level 中,避免重复创建

    2019-09-18
  • FF
    请教个问题。如果把 lua 模块用 lua_by_* 的方式引入 ngx 的 location 指令块里面,那每次请求,都会执行一遍 lua 模块中的 top level 变量和那些不是定义在函数中的全局代码块吗 ?

     
    我测了一下好像每次请求都执行一遍 ?那全局变量不是每次请求都要初始化一次啊 ?这样的话如果想在函数执行的上下文中再将一些数据保存到全局变量里面,那不是没办法用全局变量实现了 ?


    盼温老师解惑。

    作者回复: 如果你要使用全局变量, 可以写到 init 阶段,这样就只会执行一遍了。但是全局变量是不推荐使用的,在最新的OpenResty 1.15.8 版本中,增加了全局变量的检测,如果发现就会打印一条 warn 级别的日志。
    如果你希望保持函数上下文的全局数据,可以试试模块的 top level 变量。
    同时,在你测试的时候,记得保持 lua_code_cache on,并且不要在 Windows 下测试。

    2019-09-03
  • 许童童
    跟着老师一起精进。
    2019-09-02
收起评论
5
返回
顶部