Fix a worker-blocking Lua socket call and add gzip/caching for static assets
- ops/nginx_conf/targetinfo.lua's wildcard-subdomain lookup fallback used
classic LuaSocket (require("socket.unix")) instead of an OpenResty
cosocket. LuaSocket is blocking, and called from an nginx worker it
stalls the ENTIRE worker — every other in-flight connection on it — for
the round-trip to the Node app. Worse, the Node side never
newline-terminated its response, so the old blocking receive() only ever
returned via its read-timeout-then-partial-read fallback, meaning every
single cache-miss lookup paid a fixed timeout penalty while blocking the
whole worker. Replaced with an ngx.socket.tcp() cosocket (unix-domain via
"unix:/path", the only cosocket API this lua-nginx-module ships) and
newline-terminated the Node service's responses so receive() actually
completes instead of timing out. Verified against a live container:
previously this crashed OpenResty's Lua VM entirely
(ngx.socket.unix doesn't exist); fixed version resolves fresh wildcard
subdomains in ~2ms.
- Add gzip compression (`compression` middleware) and far-future
Cache-Control on static assets (7d for vendor libs under
/static-modules, 1h for the app's own /static JS/CSS, which isn't
cache-busted). The admin UI is a traditional multi-page app that loads
~13 separate vendor/app JS+CSS files on every full navigation; previously
none of them were compressed and Cache-Control was `max-age=0` (Express's
default), forcing a revalidation round-trip for every asset on every page
view.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,39 @@
|
||||
local M = {}
|
||||
|
||||
-- Function to connect to a Unix socket
|
||||
local function connect(path)
|
||||
local socket = require("socket.unix")()
|
||||
assert(socket:settimeout(.1))
|
||||
local status, err = pcall(function() assert(socket:connect(path)) end)
|
||||
if status then return true end
|
||||
return false
|
||||
-- Query the Node app's host-lookup service for a domain that missed the
|
||||
-- Redis fast path (wildcard subdomains not yet cached, see Host.addCache).
|
||||
-- Uses an OpenResty cosocket rather than the classic LuaSocket socket.unix()
|
||||
-- the previous version of this file used: LuaSocket's API is blocking and,
|
||||
-- called from an nginx worker, stalls the ENTIRE worker (every other
|
||||
-- in-flight connection on it) for the round-trip -- a real source of
|
||||
-- intermittent request latency for any wildcard host whose on-demand cache
|
||||
-- entry (1h TTL, conf.cacheTTL) had expired. resty.redis (used just above)
|
||||
-- is cosocket-based already and works fine from both the phases this module
|
||||
-- is called from (access_by_lua_block and the SSL request_domain callback),
|
||||
-- so a unix-domain cosocket is safe here too.
|
||||
local function unixLookup(json, domain)
|
||||
-- The ngx_lua cosocket API has no separate ngx.socket.unix -- a plain
|
||||
-- ngx.socket.tcp() connects to a unix domain socket when given a
|
||||
-- "unix:/path" address instead of a host/port pair.
|
||||
local sock = ngx.socket.tcp()
|
||||
sock:settimeouts(100, 100, 100) -- connect, send, read (ms)
|
||||
|
||||
local ok = sock:connect("unix:/var/run/proxy_lookup.socket")
|
||||
if not ok then return nil end
|
||||
|
||||
local ok = sock:send(json.encode({domain = domain}))
|
||||
if not ok then
|
||||
sock:close()
|
||||
return nil
|
||||
end
|
||||
|
||||
local line = sock:receive()
|
||||
sock:close()
|
||||
if not line then return nil end
|
||||
|
||||
local decodeOk, decoded = pcall(json.decode, line)
|
||||
if not decodeOk then return nil end
|
||||
return decoded
|
||||
end
|
||||
|
||||
print("In targetInfo module")
|
||||
@@ -61,20 +88,7 @@ function M.get(ngx, domain, targetInfo)
|
||||
end
|
||||
|
||||
if not res["ip"] then
|
||||
if connect("/var/run/proxy_lookup.socket") then
|
||||
local socket = require("socket.unix")()
|
||||
assert(socket:settimeout(.1))
|
||||
assert(socket:connect("/var/run/proxy_lookup.socket"))
|
||||
assert(socket:send(json.encode({domain = domain})))
|
||||
while true do
|
||||
local s, status, partial = socket:receive()
|
||||
if partial then
|
||||
res = json.decode(partial)
|
||||
socket:close()
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
res = unixLookup(json, domain) or res
|
||||
end
|
||||
|
||||
if not res["ip"] then
|
||||
|
||||
Reference in New Issue
Block a user