OpenResty 从入门到实战
温铭
OpenResty 软件基金会第一任主席,Apache APISIX 项目 VP
20903 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 52 讲
结束语 (1讲)
OpenResty 从入门到实战
15
15
1.0x
00:00/00:00
登录|注册

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

使用 ngx.timer
只能在 init_worker_by_lua 上下文中开启
拥有 root 权限
不监听端口
ngx.timer.every
ngx.timer.at
如何保证 timer 只能运行一次
使用 ngx.pipe 调用外部程序
lua-resty-shell 库
触发特权进程
特权进程特点
Nginx 主进程和工作进程
限制定时任务数量
解决周期性运行需求
ngx.timer
cosocket
共享字典缓存
OpenResty API
思考题
非阻塞的 ngx.pipe
特权进程
定时任务
超越 Web 服务器功能介绍
超越 Web 服务器:特权进程和定时任务

该思维导图由 AI 生成,仅供参考

你好,我是温铭。
前面我们介绍了 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/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

OpenResty:超越Web服务器的灵活开发平台 OpenResty不仅提供了OpenResty API、共享字典缓存和cosocket等功能,还引入了定时任务、特权进程和非阻塞的ngx.pipe,超越了Web服务器的范畴。定时任务通过ngx.timer提供了一次性和固定周期的执行功能,解决了后台定期执行任务的需求。特权进程是OpenResty的扩展,拥有和master进程一样的权限,可在init_by_lua上下文中开启,通过ngx.timer实现周期性触发。非阻塞的ngx.pipe提供了调用外部程序的非阻塞方法。这些功能使OpenResty成为一个更加灵活、强大的开发平台,为开发者提供了更多的可能性。 从上述功能可以看出,OpenResty在追求更好用的Nginx的同时,也朝着通用平台的方向靠拢,希望开发者能够统一技术栈,都用OpenResty来解决开发需求。这对于运维来说是相当友好的,因为只要部署一个OpenResty就可以了,维护成本更低。然而,由于可能存在多个Nginx worker,导致定时任务在每个worker中都运行一次,这在大多数场景下是不能接受的。因此,需要思考如何保证定时任务只能运行一次。 总的来说,OpenResty作为一个灵活的开发平台,不仅提供了丰富的功能,还在追求更好的开发体验和运维效率。通过本文的介绍,读者可以更好地了解OpenResty的特点和优势,为其在实际开发中的应用提供了更多的思路和可能性。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《OpenResty 从入门到实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(15)

  • 最新
  • 精选
  • Seven
    我想在init_worker_by_lua阶段通过timer启动一个websocket客户端一直循环收发数据会不会有问题呢?

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

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

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

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

    作者回复: 是的,没错

    2019-07-10
    2
    2
  • 旺旺
    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
    2
    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
    2
  • 英雄
    如果不能while true ,那websocket如何等待请求呢?

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

    2019-07-23
  • HelloBug
    老师好,在讲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
  • wusiration
    通过shared dict判断互斥,存在正在执行中的timer还没更新执行状态,另一个worker继续去执行; 通过判断worker的id指定某个worker执行的方式应该可以实现这一需求
    2019-07-13
    4
收起评论
显示
设置
留言
15
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部