OpenResty 通过 lua-resty-http 模块基于 cosocket 实现非阻塞 HTTP 调用,需手动安装模块、配置 resolver,并在 content_by_lua 阶段发起请求,支持超时控制、错误处理与连接池复用。

OpenResty 通过 Lua 脚本实现非阻塞 HTTP 外部接口调用,核心依赖 lua-resty-http 模块 —— 它基于 Nginx 的 cosocket(协程 socket)机制,在不阻塞 Worker 进程的前提下完成网络 I/O,真正实现高并发下的轻量级外部请求。
必须先安装 lua-resty-http 模块
OpenResty 默认不自带该模块,需手动引入:
- 从 GitHub 仓库 ledgetech/lua-resty-http 下载源码
- 提取其中三个关键文件:
http.lua、http_headers.lua、chunked.lua - 全部放入 OpenResty 的 Lua 模块路径:
lualib/resty/(例如/usr/local/openresty/lualib/resty/) - 确保 nginx 配置中已启用 resolver(用于 DNS 解析),如:
resolver 8.8.8.8 valid=30s;,放在http块内
在 location 中发起非阻塞请求
推荐使用 content_by_lua_file 或 content_by_lua_block,避免在 init 或 set 阶段调用(这些阶段不支持 cosocket):
- 定义一个路由,例如:
location /api/user { content_by_lua_file lua/fetch_user.lua; } - 在
lua/fetch_user.lua中编写实际逻辑 - 调用
http.new()创建客户端,request_uri()发起请求 —— 整个过程自动挂起协程、交由 Nginx 事件循环调度,不占用 CPU
典型代码结构(带超时与错误处理)
以下是一个生产可用的最小示例:
local http = require "resty.http"
local httpc = http.new()
<p>-- 设置连接与读写超时(单位:毫秒)
httpc:set_timeout(3000, 3000, 3000)</p><p>local res, err = httpc:request_uri("<a href="https://www.php.cn/link/67fd590c0ce05ca724b7436ced5e956d">https://www.php.cn/link/67fd590c0ce05ca724b7436ced5e956d</a>", {
method = "GET",
headers = {
["Authorization"] = "Bearer abc123",
["Accept"] = "application/json"
}
})</p><p>if not res then
ngx.status = 502
ngx.say("upstream error: ", err)
return
end</p><p>-- 透传响应头(过滤掉不可转发的字段)
for k, v in pairs(res.headers) do
if k ~= "Connection" and k ~= "Transfer-Encoding" then
ngx.header[k] = v
end
end</p><p>ngx.status = res.status
ngx.say(res.body)</p><p>httpc:close()
</p>
注意:httpc:close() 不是必须调用,但显式关闭有助于连接池复用;若开启连接池(httpc:set_keepalive()),应优先使用它代替 close。
进阶:复用连接池提升性能
高频调用外部服务时,每次新建 TCP 连接开销大。可启用内置连接池:
- 创建 client 后立即设置:
httpc:set_keepalive(60000, 100)(空闲 60 秒、最多存 100 个连接) - 后续请求会自动复用已有连接,大幅降低 handshake 和 TLS 握手耗时
- 配合
resolver的valid参数,还能避免 DNS 缓存过期导致的解析失败











