Leveraging ngx_lua for Traffic Grouping in Nginx
This article explains how to use the ngx_lua module in Nginx to assign traffic tags, implement header‑based or domain‑based routing, and integrate with dynamic upstreams for parallel testing, load testing, and gray‑release scenarios, providing code examples and configuration details.
Background
In a testing environment multiple features need to be tested in parallel, requiring Nginx to forward traffic to specific test machines based on certain information. Full‑link load testing without traffic separation impacts online users and must be performed during low‑traffic periods, which is costly and requires manual supervision. Gray‑release also needs Nginx to direct traffic to designated gray‑release servers.
ngx_lua Module
ngx_lua embeds the Lua language into Nginx, allowing developers to write Lua scripts that run inside Nginx, turning it into a high‑performance web container. The module provides many APIs for interacting with Nginx, and developers only need to learn these APIs to implement functionality.
ngx_lua Execution Phases
The module’s directives are executed within Nginx’s 11 processing phases, but not all phases run Lua code. Directives can be placed in http, server, server if, location, and location if contexts.
Directive
Phase
Scope
Description
init_by_lua
init_by_lua_file
loading‑config
http
Executed when the master process loads the configuration; typically used for global initialization or pre‑loading Lua modules.
init_worker_by_lua
init_worker_by_lua_file
starting‑worker
http
Runs when each worker process starts; often used for periodic configuration fetching, health checks, etc.
set_by_lua
set_by_lua_file
rewrite
server, server if, location, location if
Sets Nginx variables with complex logic; this is a blocking operation, so Lua code must be fast.
rewrite_by_lua
rewrite_by_lua_file
rewrite tail
http, server, location, location if
Handles rewrite phase, enabling complex forwarding or redirection logic.
access_by_lua
access_by_lua_file
access tail
http, server, location, location if
Runs during request access phase for access control.
content_by_lua
content_by_lua_file
content
location, location if
Content handler that processes the request and generates a response.
header_filter_by_lua
header_filter_by_lua_file
output‑header‑filter
http, server, location, location if
Sets response headers and cookies.
body_filter_by_lua
body_filter_by_lua_file
output‑body‑filter
http, server, location, location if
Filters response body, e.g., truncation or replacement.
log_by_lua
log_by_lua_file
log
http, server, location, location if
Log phase processing, such as recording request counts or average response time.
Setting Traffic Tags
Method 1: The client adds a tag to the request header and accesses the original domain.
if (tag == "" or checkTag(host_pass, tag) == false) then
return host_pass;
end
...
return host_pass .. "_" .. tag; set_by_lua_file $host_pass set_tag.lua;Method 2: The client appends the tag to the domain name; Nginx extracts the tag from the host, adds it to the header, and forwards the request.
local host = ngx.var.host
local hostList = split(host, ".")
local subDomain = split(hostList[1], "-")
...
ngx.req.set_header("global-route-tag", subDomain[2])
ngx.header["global-route-tag"] = subDomain[2]
...
local test_host = ipList[1] .. "." .. hostList[2] .. "." .. hostList[3]
return test_host set_by_lua_file $test_host set_test_servers.lua ;
location / {
...
proxy_pass http://$host_pass;
proxy_set_header Host $test_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}Method 1 requires external tools to add tags to headers, which is less intuitive for API testing. Method 2 reduces operational complexity and avoids host‑binding issues on corporate networks, so it is recommended for internal testing.
Integration with dyups Tagged Services
In a previous article we described smooth service rollout using Nginx. The current implementation extends the incremental update queue to support services with tags; tags are concatenated into the upstream name, enabling seamless rollout with traffic grouping.
Reference: "How ZheZhe WEB Service Achieves Smoother Changes"
Result
By publishing with tag‑based groups, the same service can be deployed to different groups, each carrying a distinct tag. This adds online traffic segmentation, solving problems for load testing, gray releases, and other scenarios.
Conclusion
Combining Nginx with Lua provides a versatile Swiss‑army‑knife‑like platform that easily solves many problems. Common practice patterns include Web Application Firewall (WAF), rate limiting, degradation, and service quality monitoring.
About the Author
Zhao Yunzhou, ZheZhe Operations Development, responsible for automation tools and platform support. Passionate about thinking and operations.
Zhuanzhuan Tech
A platform for Zhuanzhuan R&D and industry peers to learn and exchange technology, regularly sharing frontline experience and cutting‑edge topics. We welcome practical discussions and sharing; contact waterystone with any questions.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.