0Pricing
Lua Academy · 课时

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
end

UDP 协程套接字

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 反馈 — 无需本地设置。

此课程中的所有课时

  1. OpenResty 架构
  2. 在 Lua 中处理 HTTP 请求
  3. Cosocket 和非阻塞 TCP
  4. 共享内存字典
← 返回 Lua Academy