NGINX stream 子系统的简介 以及 OpenResty 对其的 支持 孙 大同 (@dndx) OpenResty Con 2017 北北京 2017 年年 10 月 21 日
关于我 90 后 曾在 LinkedIn,Cloudflare 等公司 工作 OpenResty Inc. 技术合伙 人 热爱钻研底层技术以及折腾 飞 行行爱好者 拥有固定翼私 人 飞 行行执照, 仪表 飞 行行资质以及 无 人机驾驶执照
NGINX stream 子系统的简介
NGINX stream 子系统的历史 从 2015 年年 4 月发布的 v1.9.0 开始正式出现 用于实现通 用的 TCP 以及 UDP 服务器器 功能在 v1.11.2 - v1.11.8 之间得到了了很 大的提升 v1.11.x 版本的 stream, 核 心变化 十分巨 大且不不向后兼容 截 止到 v1.13.x, 核 心部分已经趋于稳定 OpenResty 早在 2016 年年 1 月就有了了实验性的 支持
NGINX stream 子系统的连接处理理 (TCP) O/S, event subsystem and stream_core_module TCP 3-way handshake accept() session 初始化 stream phase engine postaccept preaccess access ssl log output filter content preread 清理理
NGINX stream 子系统的连接处理理 (UDP) O/S, event subsystem and stream_core_module 收到 UDP 数据包 recv() session 初始化 stream phase engine postaccept preaccess access ssl log output filter content preread 清理理
stream-lua-nginx-module 对最新 NGINX 核 心的 支持 Kong Inc. 赞助了了 stream-lua-nginx-module 的开发 完全基于最新的 lua-nginx-module 代码重写 重写过程中加 入了了对新的 phase 系统和变量量系统的 支持 增加了了新的 API 来适应 stream 模块的特殊需求 新的 meta-lua-nginx-module
no location block
preread_by_lua 访问控制 高级代理理策略略 可以使 用会 yield 的 API 可以向客户输出内容 不不受 preread_buffer_size 和 preread_timeout 的限制
balancer_by_lua API 于 lua-nginx-module 现有的完全兼容 需要在 stream 的 block 下单独定义 upstream state_name, status_code = balancer.get_last_failure() balancer.set_timeouts(connect_timeout, send_timeout, read_timeout)
log_by_lua 发 生在连接即将被关闭时 不不能 yield 可以使 用 ngx.timer.* API 可以访问所有的变量量以及 ngx.ctx
stream-lua-nginx-module 使 用过程中的注意事项 避免频繁在请求的内存池上分配 UDP 子系统对数据包的特殊处理理 不不要在没有完全清空操作系统的 socket 读缓冲区的情况下关闭连接 新的 API:tcpsock:shutdown() 用来模拟 lingering close
Lingering close Kernel socket 读缓存 数据 NGINX 连接读缓存 数据 close() will cause RST
tcpsock:shutdown local LINGERING_TIME = 30 -- 30 seconds local LINGERING_TIMEOUT = 5000 -- 5 seconds local ok, err = sock:shutdown("send") if not ok then ngx.log(ngx.err, "failed to shutdown: ", err) return end local deadline = ngx.time() + LINGERING_TIME sock:settimeouts(nil, nil, LINGERING_TIMEOUT) repeat local data, _, partial = sock:receive(1024) until (not data and not partial) or ngx.time() >= deadline Source: https://github.com/openresty/stream-lua-nginx-module#tcpsockshutdown
stream-lua-nginx-module 的开发思路路 I/O 主要依靠于 ngx.req.socket, 只 支持 raw socket 有少量量的 ngx.say(),ngx.print() 的 支持 可以利利 用 preread_by_lua,proxy 模块和 balancer_by_lua 来 高效的转发
stream-lua-nginx-module 未来的功能 ssl_certificate_by_lua* access_by_lua* shdict 跨 子系统的共享 lua-resty-core 的集成
例例 子 :echo 服务器器 stream { server { listen 1234; content_by_lua_block { local sock, err = ngx.req.socket() if not sock then ngx.exit(500) end while true do local data data, err = sock:receive('*l') if not data then return ngx.exit(200) end } } } end local sent sent, err = sock:send(data.. '\n') if err then return ngx.exit(200) end
Demo: telnet 聊天室 https://github.com/dndx/telnet-chat
stream-lua-nginx-module 模块在 OpenResty Edge 2 中的应 用 已经在 用 类 memcached 协议的服务 DNS 服务器器 很快会有 基于规则的四层流量量代理理 Routing Platform
OpenResty Edge 2 Routing Platform Edge Admin cluster2.node1.pri vileged.service 集群 1 集群 2 Node 1 Node 2 Node n 数据 Node 1 Node 2 Node n
代码 生成过程 meta-lua-nginx-module 渲染 渲染 lua-nginx-module NGINX stream-lua-nginxmodule 编译链接 二进制 文件
更更多信息 https://github.com/openresty/stream-lua-nginx-module https://github.com/openresty/meta-lua-nginx-module https://openresty.com Email: datong#openresty.com 欢迎贡献 PR!
Questions?
Thank You!