Cosocket 和非阻塞 TCP
使用 ngx.socket.tcp 在 content_by_lua 中建立异步后端连接。
Cosocket 和非阻塞 TCP 是 CoddyKit 上的免费 Lua Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Lua Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Lua Academy 课程共包含 4 节课。
什么是协程套接字
OpenResty 协程套接字是与 Nginx 事件循环集成的非阻塞 TCP/UDP 套接字。等待数据时,它们会让出协程,使工作进程可以处理其他请求。
创建 TCP 协程套接字
请使用 ngx.socket.tcp() 创建协程套接字。当 I/O 操作可能阻塞时,连接、发送和接收都会自动让出协程。
-- content_by_lua_block
local sock = ngx.socket.tcp()
local ok, err = sock:connect("redis.local", 6379)
if not ok then
ngx.log(ngx.ERR, "Connect failed: ", err)
return ngx.exit(500)
end发送数据
sock:send(data) 发送一个字符串。成功时返回已发送的字节数,失败时返回 nil + 错误信息。
local bytes, err = sock:send("PING\r\n")
if not bytes then
ngx.log(ngx.ERR, "Send error: ", err)
end接收数据
sock:receive(pattern) 读取数据。模式包括:"*l" 读取一行,"*a" 读取直到连接关闭的所有数据,数字则表示精确读取 N 个字节。
local data, err = sock:receive("*l")
if not data then
ngx.log(ngx.ERR, "Receive error: ", err)
return ngx.exit(500)
end
ngx.say("Response: " .. data)设置超时
请设置连接、发送和接收超时,以防止操作一直挂起。
sock:settimeout(1000) -- 1 second timeout
-- or separate timeouts:
sock:settimeouts(1000, 5000, 5000) -- connect, send, receive (ms)连接池
sock:setkeepalive(timeout, pool_size) 会将套接字放回连接池以便重复使用。这对 Redis/MySQL 的性能至关重要。
sock:setkeepalive(60000, 100) -- 60s timeout, pool size 100发起 HTTP 请求
使用协程套接字实现一个简单的 HTTP/1.0 GET 请求。
local function httpGet(host, path)
local sock = ngx.socket.tcp()
sock:connect(host, 80)
sock:send("GET " .. path .. " HTTP/1.0\r\nHost: " .. host .. "\r\n\r\n")
local resp = sock:receive("*a")
sock:close()
return resp
endUDP 协程套接字
ngx.socket.udp() 创建一个 UDP 协程套接字。它适合用于报告 statsd 指标。
local udp = ngx.socket.udp()
udp:setpeername("statsd.local", 8125)
udp:send("requests:1|c")错误处理模式
所有协程套接字方法都遵循 Lua 约定:失败时返回 nil + 错误字符串。请始终检查这两个返回值。
协程套接字的限制
协程套接字不能用于:init_by_lua、set_by_lua、header_filter_by_lua。请仅在内容、访问和重写阶段使用它们。
性能比较
协程套接字可以达到与基于原始 epoll 的 C 代码相同的吞吐量,因为它们直接使用 Nginx 的 I/O 机制。不会产生额外的线程或进程开销。
协程套接字问题
当协程套接字等待速度缓慢的服务器提供数据时,会发生什么?
回顾:协程套接字与非阻塞 TCP
OpenResty 协程套接字提供非阻塞 TCP/UDP,并会在 I/O 操作期间让出协程,从而实现高并发。使用 setkeepalive 进行连接池管理。设置超时以避免操作挂起。它们仅可用于内容、访问和重写阶段。
常见问题解答
「Cosocket 和非阻塞 TCP」课时是免费的吗?
是的 — 「Cosocket 和非阻塞 TCP」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Lua Academy 课程的其余内容,请升级到 CoddyKit PRO。 Lua Academy 课程共包含 4 节课。
「Cosocket 和非阻塞 TCP」这节课中我会学到什么?
使用 ngx.socket.tcp 在 content_by_lua 中建立异步后端连接。 你通过在浏览器中直接运行的动手代码来练习 Lua Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Lua Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Lua Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「Cosocket 和非阻塞 TCP」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Lua Academy 课中编写并运行代码吗?
能。每节 Lua Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- OpenResty 架构
- 在 Lua 中处理 HTTP 请求
- Cosocket 和非阻塞 TCP
- 共享内存字典