news 2026/5/28 5:11:01

Openresty基础知识详解:轻松驾驭高性能web网关

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Openresty基础知识详解:轻松驾驭高性能web网关

nginx 采用模块化设计,使得每一个 http 模块可以仅专注于完成一个独立的、简单的功能,而一个请求的完整处理过程可以由无数个 http 模块共同合作完成。为了灵活有效地指定下一个http 处理模块是哪一个;http 框架依据常见的的处理流程将处理阶段划分为 11 个阶段,其中每一个阶段都可以由任意多个http 模块流水式地处理请求。

openresty 将 lua 脚本嵌入到 nginx 阶段处理的末尾模块下;这样以来并不会影响 nginx 原有的功能,而是在 nginx 基础上丰富它的功能。

嵌入 lua 的优点是:使用 openresty 开发,不需要重新编译,直接修改 lua 脚本,重新启动即可。

抽象:虚拟主机对应一个lua虚拟机,每个请求对应一个协程。

Lua 模块指令顺序:

交互流程:

Lua嵌入nginx:

(1)init_by_lua。master fork之前调用,此阶段初始化的数据将被复制多个worker进程中。它的作用有:加载一些耗时模块、设置全局变量、初始化共享内存等。在 nginx 重新加载配置文件时,运行里面 lua 脚本,常用于全局变量的申请。例如 lua_shared_dict 共享内存的申请,只有当 nginx 重启后,共享内存数据才清空,这常用于统计。

(2)init_worker_by_lua。master fork之后,worker初始化时调用,在每个 Nginx 工作进程启动时执行;此阶段初始化的数据各个worker可不同。它很重要的一个作用是开启定时器。

(3)ssl_certificate_by_lua。ssl阶段,在握手时设置安全证书。

(4)set_by_lua。用于设置nginx变量;设置一个变量,常用与计算一个逻辑,然后返回结果,该阶段不能运行Output API、Control API、Subrequest API、Cosocket API。

(5)rewrite_by_lua。用于执行内部url重写或外部重定向。在 access 阶段前运行,主要用于 rewrite url。

(6)access_by_lua。用于访问控制。这条指令运行于 nginx access 阶段的末尾,因此总是在 allow 和 deny 这样的指令之后运行,它们同属 access 阶段。可用来判断请求是否具备访问权限。

(7)content_by_lua。用于内容管理。此阶段是所有请求处理阶段中最为重要的一个,运行在这个阶段的配置指令一般都肩负着生成内容(content)并输出HTTP 响应。

(8)header_filter_by_lua。设置应答消息的头部信息;一般只用于设置 Cookie 和 Headers 等。

(9)body_filter_by_lua。用于修改应答body的内容。一般会在一次请求中被调用多次,因为这是实现基于 HTTP 1.1 chunked 编码的所谓“流式输出”的。

(10)log_by_lua。用于log请求处理阶段,用lua处理日志。该阶段总是运行在请求结束的时候,用于请求的后续操作,如在共享内存中进行统计数据,如果要高精确的数据统计,应该使用 body_filter_by_lua

(11)balancer_by_lua。上游服务器的负载均衡。

四、责任链

责任链模式是一种行为型设计模式,多个对象都有机会处理请求,避免请求的发送者和接收者之间产生紧密的耦合关系。在该模式中,请求的接收者被组织成一个处理对象链表,请求沿着这个链条传递,直到链中某个对象对其进行处理。

OpenResty 中,Nginx 的请求处理阶段天然体现出责任链模式。每个 Nginx 阶段都可以看作链中的一个“处理者”,lua-nginx-module在这些预设的处理阶段中插入自定义的 Lua 逻辑。OpenResty 通过ngx.exit()函数提供对责任链流程的精细控制:

  • ngx.exit(ngx.OK)ngx.exit(ngx.DECLINED): 表示当前阶段的处理已完成,请求将继续流转到 Nginx 处理链的下一个阶段。

  • ngx.exit(HTTP_STATUS_CODE)(例如ngx.exit(200),ngx.exit(403),ngx.exit(500)): 表示当前请求的处理已结束,Nginx 将立即发送相应的 HTTP 状态码和响应体,并终止后续所有阶段的处理。这使得 Lua 脚本能够根据业务逻辑随时中断请求处理,例如在认证失败时直接返回 403 错误。

按需在处理链的任何环节进行干预,实现灵活的请求处理流程控制。

五、cosocket

cosocket是 OpenResty 为 Nginx 引入的最核心、最具革命性的功能之一让Lua 脚本能够在不阻塞 Nginx Worker 进程的前提下,进行网络 I/O 操作,在 HTTP 请求处理过程中无缝地访问各种第三方服务。

cosocket的实现原理结合了 Nginx 的事件驱动机制和 Lua 的协程 (coroutine) 特性,实现了非阻塞的网络 I/O。以同步的代码风格编写异步的网络操作,简化复杂异步编程的难度。

引入cosocket后,单线程的 Nginx Worker 进程内部相当于拥有了多条“并行”的同步逻辑线(即 Lua 协程)。一个 Lua 协程发起网络 I/O 请求,如果数据尚未就绪,协程会主动让出 CPU 控制权,把 I/O 操作注册到 Nginx 的事件循环中,并进入挂起状态。Nginx Worker 进程则继续处理其他请求或唤醒其他已就绪的协程。一旦 I/O 事件完成,Nginx 的事件循环会唤醒之前挂起的 Lua 协程,使其从上次中断的地方继续执行。这种“让出”和“唤醒”的机制,确保Nginx Worker 进程始终保持非阻塞,处理大量并发连接。

通过 Lua 协程把底层 Socket 的异步事件编程转化为上层同步处理的编码体验,cosocket提升了 OpenResty 的开发效率和性能。基于cosocket,OpenResty 社区和官方开发了大量高质量的第三方库:

  • ngx.socket.tcp: 用于通用的 TCP 客户端通信。

  • ngx.socket.udp: 用于通用的 UDP 客户端通信。

  • resty.redis: 高性能 Redis 客户端库。

  • resty.mysql: 高性能 MySQL 客户端库。

  • resty.postgres: 高性能 PostgreSQL 客户端库。

  • resty.memcached: 高性能 Memcached 客户端库。

  • resty.http: 高性能 HTTP/HTTPS 客户端库。

  • resty.kafka: Kafka 客户端库。

  • 等等。

这些库让 OpenResty 集成和访问各种外部服务变得异常简单。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 0:32:58

2024年8月中文大模型战力榜:国产模型全面崛起改写全球竞争格局

一、行业背景与研究意义 【免费下载链接】DeepSeek-V2-Chat-0628 DeepSeek-V2-Chat-0628,开源创新之作,AI聊天机器人性能卓越,编码能力出众。在LMSYS Chatbot Arena榜单脱颖而出,多项任务表现领先。升级优化,体验更佳&…

作者头像 李华
网站建设 2026/5/26 13:26:31

LeetCode热题100--215. 数组中的第K个最大元素--中等

题目 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输入: [3,2,1,5,6,4]…

作者头像 李华
网站建设 2026/5/27 21:08:10

C语言递归函数的习题笔记

字符串逆序的递归实现(C语言)在C语言中,实现字符串逆序的递归方法是一种高效且直观的方式。递归的核心思想是将问题分解为更小的子问题:通过交换字符串的首尾字符,然后递归地处理剩余的子字符串,直到整个字…

作者头像 李华
网站建设 2026/5/27 11:38:39

Flutter 通用弹窗组件 CustomDialogWidget:全自定义布局 + 多场景适配

在 Flutter 开发中,弹窗是交互反馈、信息确认、选项选择的核心载体。原生 showDialog 存在样式固化、布局灵活度低、多按钮适配差等问题,重复开发易导致 APP 内弹窗风格混乱。本文封装的 CustomDialogWidget 整合 “头部 内容 按钮区” 全自定义、单选…

作者头像 李华
网站建设 2026/5/26 12:08:46

Flutter 通用列表项组件 CommonListItemWidget:全场景布局 + 交互增强

在 Flutter 开发中,列表是数据展示的核心载体,而列表项的样式统一性与灵活性直接影响开发效率与用户体验。原生 ListTile 存在图标位置固定、不支持徽章提示、自定义布局受限等问题。本文封装的 CommonListItemWidget 整合 “图标 / 图片 标题 副标题 …

作者头像 李华