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从入门到实战
登录|注册

20 | 超越 Web 服务器:特权进程和定时任务

温铭 2019-07-10
你好,我是温铭。
前面我们介绍了 OpenResty API、共享字典缓存和 cosocket。它们实现的功能,都还在 Nginx 和 Web 服务器的范畴之内,算是提供了开发成本更低、更容易维护的一种实现,提供了可编程的 Web 服务器。
不过,OpenResty 并不满足于此。我们今天就挑选几个,OpenResty 中超越 Web 服务器的功能来介绍一下。它们分别是定时任务、特权进程和非阻塞的 ngx.pipe。

定时任务

在 OpenResty 中,我们有时候需要在后台定期地执行某些任务,比如同步数据、清理日志等。如果让你来设计,你会怎么做呢?最容易想到的方法,便是对外提供一个 API 接口,在接口中完成这些任务;然后用系统的 crontab 定时调用 curl,来访问这个接口,进而曲线地实现这个需求。
不过,这样一来不仅会有割裂感,也会给运维带来更高的复杂度。所以, OpenResty 提供了 ngx.timer 来解决这类需求。你可以把ngx.timer ,看作是 OpenResty 模拟的客户端请求,用以触发对应的回调函数。
其实,OpenResty 的定时任务可以分为下面两种:
ngx.timer.at,用来执行一次性的定时任务;
ngx.time.every,用来执行固定周期的定时任务。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《OpenResty从入门到实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(14)

  • wusiration
    通过shared dict判断互斥,存在正在执行中的timer还没更新执行状态,另一个worker继续去执行;
    通过判断worker的id指定某个worker执行的方式应该可以实现这一需求
    2019-07-13
    2
  • Seven
    我想在init_worker_by_lua阶段通过timer启动一个websocket客户端一直循环收发数据会不会有问题呢?

    作者回复: while True 的循环吗?我的建议是跑一段时间,比如 5 分钟,就退掉,然后启动一个新的客户端。

    2019-07-14
    1
  • manatee
    想请问下特权进程是怎么回事,启动or本身就是普通用户。如何获取root权限呢,另外特权进程的使用场景有哪些可以介绍下吗

    作者回复: 特权进程和master 进程的权限一样,如果 master 是普通用户,那特权进程也不可能拿到 root 权限。
    一般用特权进程来清理日志、重启 OpenResty 自身等需要高权限的任务。

    2019-07-10
    1
  • manatee
    可以通过查看worker id,在指定worker下执行

    作者回复: 是的,没错

    2019-07-10
    1
    1
  • 旺旺
    老师,在init_worker_by_lua_block里
    local ok, err = ngx.timer.every(30, reset_server_list)
    ok, err = ngx.timer.at(0, reget_ssl_certificate)
    ok, err = ngx.timer.every(3600, reget_ssl_certificate)
    写了三个定时器,怎么执行的效果不是想象中那样呢?
    本来是想着一开始的时候就执行一次reget_ssl_certificate,然后每隔1个小时再执行一次reget_ssl_certificate的。
    现在就算过了30秒reset_server_list也不执行。
    如果只写一个“local ok, err = ngx.timer.every(30, reset_server_list)”是可以的。
    意思是ngx.timer.every和ngx.timer.at不能同时混用吗?

    作者回复: 是可以混用的,它们之间不会互相影响的。如果你确定这里有bug,可以整理一个最小的复现代码,给 OpenResty 提交 issue

    2019-09-23
  • 旺旺
    发现在init_by_lua_block里面开了特权进程后,如果init_worker_by_lua_block又有io.open创建文件操作,那么后面在worker进程里面第一次创建文件时的用户也是root了,然后后面worker里面写文件的时候,会报:
    failed to open file in append mode. error message: /tmp/wscmd_response.log: Permission denied,
    因为/tmp/wscmd_response.log一开始是用root身份创建的,后面再用nobody去写的时候,就会报错。
    2019-09-18
  • 搞怪者😘 😒 😏 👿
    这个定时器跟用curl是一样的嘛,怎么实现毫秒级定时,如果在压力很大的环境下,这样的定时器不就会消耗端口资源吗
    2019-09-17
  • 旺旺
    local f, err = io.open(ngx.config.prefix() .. "/logs/nginx.pid", "r")
    老师,这个代码也是Lua 的标准库,是不是也是阻塞的,又改采用什么方式优化呢?

    作者回复: 磁盘 IO 没有什么优化的方法,这里有一个使用 nginx threads pool 来模拟实现 "非阻塞"的方案:https://github.com/tokers/lua-io-nginx-module,你可以参考下。

    2019-08-29
  • 英雄
    如果不能while true ,那websocket如何等待请求呢?

    作者回复: 可以 while true,但是有一个阈值,比如循环 1000 次之后退出循环,重新来一次。

    2019-07-23
  • 回家
    老师好,在讲ngx.timer的时候,说如果在回调函数里使用while true+sleep的方式循环执行任务,因为timer本质是一个请求,上面所说的实现会导致这个请求常驻,这些都是可以理解的,后面说会导致资源的泄露,这个怎么理解呢?

    作者回复: 泄漏这个词可能不太恰当,就是会导致很多 Lua 或者 C 对象无法得到释放,长期运行会有很多碎片。

    2019-07-14
  • helloworld
    local function reload(premature),老师,这个函数的参数premature是什么意思,在这段代码中有什么用呢

    作者回复: ngx.timer 的文档是有提到它的作用的:
    the premature argument takes a boolean value indicating whether it is a premature timer expiration or not.
    Premature timer expiration happens when the Nginx worker process is trying to shut down, as in an Nginx configuration reload triggered by the HUP signal or in an Nginx server shutdown. When the Nginx worker is trying to shut down, one can no longer call ngx.timer.at to create new timers with nonzero delays and in that case ngx.timer.at will return a "conditional false" value and a string describing the error, that is, "process exiting".
    简单的说,就是在 Nginx 重启后者关闭的时候,就不要再去创建 timer 了。

    2019-07-14
  • Rye
    ngx.worker.id() == 0 应该是第一个worker

    作者回复: 是的,没错

    2019-07-11
  • chundonglinlin
    worker slot
    2019-07-10
  • 星亦辰
    share dict存取执行状态,就可以完成互斥了
    2019-07-10
收起评论
14
返回
顶部