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

15 | OpenResty 和别的开发平台有什么不同?

跨阶段的变量
全局变量、局部变量和模块变量
ngx.sleep 实现比标准 Lua 的优势
API 使用限制
不同阶段的作用
欢迎留言和分享
理解概念的重要性
变量和生命周期
非阻塞
阶段
ngx.sleep 源码分析
Lua 协程与 NGINX 事件机制配合
NGINX 的事件驱动
OpenResty 架构图
准备开始学习 OpenResty 提供的 API
学习了 OpenResty 的两个基石:NGINX 和 LuaJIT
写在最后
基本概念
原理
温铭
OpenResty 和别的开发平台有什么不同?

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

你好,我是温铭。
上一模块中, 你已经学习了 OpenResty 的两个基石:NGINX 和 LuaJIT,相信你已经摩拳擦掌,准备开始学习 OpenResty 提供的 API 了吧?
不过,别着急,在这之前,你还需要再花一点儿时间,来熟悉下 OpenResty 的原理和基本概念。

原理

在前面的 LuaJIT 内容中,你已经见过下面这个架构图:
这里我再详细解释一下。
OpenResty 的 master 和 worker 进程中,都包含一个 LuaJIT VM。在同一个进程内的所有协程,都会共享这个 VM,并在这个 VM 中运行 Lua 代码。
而在同一个时间点上,每个 worker 进程只能处理一个用户的请求,也就是只有一个协程在运行。看到这里,你可能会有一个疑问:NGINX 既然能够支持 C10K (上万并发),不是需要同时处理一万个请求吗?
当然不是,NGINX 实际上是通过 epoll 的事件驱动,来减少等待和空转,才尽可能地让 CPU 资源都用于处理用户的请求。毕竟,只有单个的请求被足够快地处理完,整体才能达到高性能的目的。如果采用的是多线程模式,让一个请求对应一个线程,那么在 C10K 的情况下,资源很容易就会被耗尽的。
在 OpenResty 层面,Lua 的协程会与 NGINX 的事件机制相互配合。如果 Lua 代码中出现类似查询 MySQL 数据库这样的 I/O 操作,就会先调用 Lua 协程的 yield 把自己挂起,然后在 NGINX 中注册回调;在 I/O 操作完成(也可能是超时或者出错)后,再由 NGINX 回调 resume 来唤醒 Lua 协程。这样就完成了 Lua 协程和 NGINX 事件驱动的配合,避免在 Lua 代码中写回调。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

OpenResty 是一个基于 NGINX 和 LuaJIT 的开发平台,通过与 NGINX 的协同工作,实现了高性能的特点。该平台提供了丰富的 API 和灵活的阶段概念,使得开发者能够更好地利用其特性进行开发。文章首先介绍了 OpenResty 的原理,包括 LuaJIT VM 在 master 和 worker 进程中的运行机制,以及 Lua 协程与 NGINX 事件驱动的配合。其次,文章提到了 OpenResty 中的阶段概念和非阻塞特点,强调了其提供的 API 都是非阻塞的,并且每个 API 都有特定的使用阶段限制。最后,通过具体的示例说明了如何使用 `ngx.sleep` 实现非阻塞的等待操作。此外,文章还涉及了变量的生命周期和模块变量的特性,以及跨阶段的变量处理方式,如使用 `ngx.ctx` 存储基于请求的 Lua 数据。总的来说,OpenResty 通过与 NGINX 的协同工作,实现了高性能的特点,同时提供了丰富的 API 和灵活的阶段概念,使得开发者能够更好地利用其特性进行开发。

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

全部留言(15)

  • 最新
  • 精选
  • jackstraw
    老师说的,“访问模块变量的时候,你最好保持只读,而不要尝试去修改,不然在高并发的情况下会出现 race”这个问题有点疑惑。既然每个worker同一时间只会有一个请求在进行中,那么同一时间只会有一个请求正在操作这个模块变量啊?怎么会出现race?

    作者回复: 如果修改的中途有 yield 操作,就可能会有 race。没有 yield 的话自然没有。

    2019-08-12
    3
    5
  • 宝仔
    location配置如下: location / { access_by_lua_file lua/access.lua; content_by_lua_file lua/content.lua; } access_by_lua_file内容如下: ngx.var.res = "test" content_by_lua_file内容如下: ngx.say(ngx.var.res) 老师你好,这样子也说可以做到变量跨阶段读写的

    作者回复: 是的

    2019-09-05
    1
  • FF
    温老师能否针对 OR 进程和协程的交互和他俩的协作关系展开讲讲。 比如在同一个时间点上,每个 worker 进程只能处理一个用户的请求,也就是只有一个协程在运行。那如果协程阻塞,这个 worker 进程是否也在阻塞状态 ?协程是不是由 OR 的 worker 进程来创建 ,单个请求完后就消亡 ? 或者这方面有什么资料可以推荐下吗? 感谢。盼复。

    作者回复: 其实不是只有一个协程,是有一个父协程和子协程。这方面推荐 codedump 老师的源码分析:https://www.codedump.info/post/20190501-lua-stream/,内容质量很高

    2019-07-01
    1
  • life_牛
    老师,编译openresty时候出现 error SSE 4.2 not found这个错误,网上有说cpu太老 如何处理这样的问题,还是可以忽略

    作者回复: OpenResty 的一些特性用到了 SSE 4.2 指令集,这个只能换机器了

    2019-09-12
    2
  • 上善若水
    老师您好,看你的最佳实践中,遇到一个问题请教一下,在引入第三方resty库时,我根据配置请求不是返回的百度首页,是一个 <!DOCTYPE html> <!--STATUS OK--> 是什么问题?多谢。

    作者回复: 是否有更详细的信息?可以放到 gist 里面

    2019-07-02
  • helloworld
    说一段比较绕口的废话来理解协程、异步: openresty中的一个worker进程中只有一个线程,该线程是轻量化的线程,也可以叫微线程,也可以称为协程,所谓协程就是处理协程对象的线程,所谓协程对象就是异步化的代码片段,所谓异步化就是遇到网络I/O磁盘I/O等耗时I/O操作时使CPU停止等待I/O,马上去处理下一个协程对象,避免白白浪费CPU时间,这就是非阻塞,具体说应该叫CPU非阻塞,当之前的协程对象I/O完成后,CPU在回去继续处理该协程对象剩余的代码,当然了继续处理过程中遇到I/O阻塞还会继续中断跳出去执行其他协程对象,往复...
    2019-06-28
    9
  • 阳光梦
    老师,基于worker的缓存模块,对数据改写操作时候也有竞争?
    2019-06-28
    2
    3
  • DC
    openresty的日志路径是如何配置的,这个问题一直困扰我,ngx.log打印不同级别的日志,文件位置可以配置吗,默认是error.log吗
    2021-03-15
    1
  • ꧁༺༻꧂
    温大,请教个问题,我运行实例,require("hello") 提示找不到,错误信息如下: /home/jin/geektime/lua/import.lua:1: module 'data' not found: no field package.preload['data'] no file '/usr/local/openresty/site/lualib/data.ljbc' no file '/usr/local/openresty/site/lualib/data/init.ljbc' no file '/usr/local/openresty/lualib/data.ljbc' no file '/usr/local/openresty/lualib/data/init.ljbc' no file '/usr/local/openresty/site/lualib/data.lua' no file '/usr/local/openresty/site/lualib/data/init.lua' no file '/usr/local/openresty/lualib/data.lua' no file '/usr/local/openresty/lualib/data/init.lua' no file './data.lua' no file '/usr/local/openresty/luajit/share/luajit-2.1.0-beta3/data.lua' no file '/usr/local/share/lua/5.1/data.lua' no file '/usr/local/share/lua/5.1/data/init.lua' no file '/usr/local/openresty/luajit/share/lua/5.1/data.lua' no file '/usr/local/openresty/luajit/share/lua/5.1/data/init.lua' no file '/usr/local/openresty/site/lualib/data.so' no file '/usr/local/openresty/lualib/data.so' no file './data.so' no file '/usr/local/lib/lua/5.1/data.so' no file '/usr/local/openresty/luajit/lib/lua/5.1/data.so' no file '/usr/local/lib/lua/5.1/loadall.so' stack traceback: coroutine 0: [C]: in function 'require' /home/jin/geektime/lua/import.lua:1: in main chunk, client: 127.0.0.1, server: , request: "GET /import HTTP/1.1", host: "127.0.0.1:8080" 但是 "./data.lua" 明明是存在的 -------- $ cat lua/data.lua local _M = {} _M.color = { red = 1, blue = 2, green = 3 } return _M ------ $ cat lua/import.lua local hello = require ("data") ngx.say(hello.color.green) ------ $ cat conf/nginx.conf ...... location /import { content_by_lua_file lua/import.lua; } ....
    2022-12-09归属地:四川
    1
  • 猪小擎
    同步和异步,阻塞和非阻塞,这都是没有好和坏的区别的,以为异步非阻塞比同步阻塞好,很片面,而且不对。如果硬要说阻塞和非阻塞哪个更好一点,应该是阻塞比非阻塞更好一点。用一个cpu空转的代码来做阻塞的例子,这也太黑阻塞了吧。空转不等于阻塞,空转用100%CPU,阻塞不消耗CPU。
    2022-04-06
收起评论
显示
设置
留言
15
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部