How to Mirror Traffic in Nginx Using the ngx_http_mirror_module
This guide explains why and how to copy production traffic to a pre‑release environment, walks through installing Nginx, configuring the ngx_http_mirror_module, building Nginx from source with the module, and provides useful commands and documentation links.
1. Requirements
Copying production traffic to a pre‑release or test environment offers many benefits:
Validate functionality and service performance.
Use real traffic without generating synthetic data, avoiding impact on live users.
Unlike gray releases, mirrored traffic does not affect real traffic.
Facilitate troubleshooting of online issues.
Support testing after service refactoring.
The Nginx ngx_http_mirror_module enables traffic mirroring.
2. Install Nginx
Create a yum repository file /etc/yum.repos.d/nginx.repo with the following content:
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=trueInstall Nginx: yum install nginx The default configuration file is nginx.conf, typically located in /usr/local/nginx/conf, /etc/nginx, or /usr/local/etc/nginx. Start Nginx with:
# Start Nginx
nginx
# Fast shutdown
nginx -s stop
# Graceful shutdown
nginx -s quit
# Reload configuration
nginx -s reload
# Reopen log files
nginx -s reopen
# List Nginx processes
ps -ax | grep nginxWhen the master process receives a reload signal, it checks the new configuration syntax, starts new worker processes, and gracefully shuts down old workers after they finish existing connections. The master PID is stored in nginx.pid (usually under /usr/local/nginx/logs or /var/run).
Alternative stop command: kill -s QUIT 3997 Initial configuration example:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}3. ngx_http_mirror_module
The module (available since Nginx 1.13.4) creates background mirror sub‑requests for the original request; responses are ignored.
Conceptually, the mirror acts like a replica site that captures all original requests, allowing you to replay traffic elsewhere.
Simple example from the official documentation:
location / {
mirror /mirror;
proxy_pass http://backend;
}
location = /mirror {
internal;
proxy_pass http://test_backend$request_uri;
}If the request body should be mirrored, enable it before creating the sub‑request:
location / {
mirror /mirror;
mirror_request_body off;
proxy_pass http://backend;
}
location = /mirror {
internal;
proxy_pass http://log_backend;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}Because the default Nginx package may lack this module, compile Nginx from source with the desired modules:
Download source from http://nginx.org/en/download.html and configure:
./configure \
--sbin-path=/usr/local/nginx/nginx \
--conf-path=/usr/local/nginx/nginx.conf \
--pid-path=/usr/local/nginx/nginx.pid \
--with-http_ssl_module \
--without-http_limit_req_module \
--without-http_mirror_module \
--with-pcre=../pcre-8.43 \
--with-zlib=../zlib-1.2.11 \
--add-module=/path/to/ngx_devel_kit \
--add-module=/path/to/lua-nginx-module
make && make installExample configuration using upstreams and mirroring:
upstream api.abc.com {
server 127.0.0.1:8080;
}
upstream tapi.abc.com {
server 127.0.0.1:8081;
}
server {
listen 80;
# Source site
location /api {
proxy_pass http://api.cjs.com;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Traffic mirroring
mirror /newapi;
mirror /mirror2;
mirror /mirror3;
# Mirror request body
mirror_request_body on;
}
# Mirror site
location /tapi {
proxy_pass http://tapi.cjs.com$request_uri;
proxy_pass_request_body on;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}4. Documentation
Official Nginx documentation:
http://nginx.org/en/docs/
http://nginx.org/en/docs/http/ngx_http_mirror_module.html
http://nginx.org/en/docs/beginners_guide.html
http://nginx.org/en/docs/http/ngx_http_core_module.html#location
http://nginx.org/en/docs/configure.html
Third‑party resources:
http://luajit.org/
https://www.nginx.com/resources/wiki/
https://www.nginx.com/resources/wiki/modules/lua/
https://www.nginx.com/resources/wiki/modules/index.html
https://github.com/openresty/lua-nginx-module
Additional useful commands:
# Show process runtime
ps -eo pid,user,lstart,etime,cmd | grep nginx
# Count established connections
netstat -an | grep ESTABLISHED | wc -l
# Count connections on port 80
netstat -an | grep ":80" | wc -lSigned-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
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.
