Understanding Nginx Architecture, Process Model, and Performance Optimization
This article provides a comprehensive overview of Nginx’s high‑performance features, module architecture, process and I/O models, FastCGI integration with PHP‑FPM, configuration best practices, tuning techniques, and common error troubleshooting, offering practical guidance for optimizing and securing Nginx deployments.
NGINX is a high‑performance load balancer, cache and web server that powers more than 40% of the world’s busiest websites. It excels in handling high concurrency through an event‑driven, asynchronous non‑blocking architecture.
Key Features
High performance via event‑driven design.
Reverse proxy with load balancing and failover.
Static file serving with fast transfer.
Dynamic content handling through languages such as PHP and Python.
Reverse‑proxy caching to accelerate responses.
SSL/TLS support for secure communication.
Extensible modular architecture with core, basic and third‑party modules.
Modules and Working Principle
NGINX consists of a tiny core and a set of modules. The core parses the configuration file and maps a request to a location block; each directive inside the location activates a specific module to perform the work.
Modules are classified structurally as:
Core modules: HTTP, EVENT, MAIL.
Basic modules: HTTP Access, FastCGI, Proxy, Rewrite.
Third‑party modules: e.g., HTTP Upstream Request Hash, Notice, Access Key. Functionally they fall into three categories: Handlers : directly generate the response and modify headers (only one per request). Filters : modify the output of handlers before it is sent to the client. Proxies : interact with upstream services such as FastCGI, uWSGI, etc. Process Model NGINX starts a master process that manages one or more worker processes. The master handles signals, monitors workers, and performs graceful reloads. Workers are single‑threaded processes that accept connections, read, process, and return responses. When a SIGHUP is received, the master reloads the configuration, spawns new workers, and tells old workers to finish existing requests before exiting. Workers accept connections using a shared accept_mutex to ensure only one worker accepts a given socket at a time, then process the request entirely within that worker. Asynchronous Non‑Blocking I/O NGINX uses an event loop similar to libevent . The steps are: while (true) { for t in run_tasks: t.handler(); update_time(&now); timeout = ETERNITY; for t in wait_tasks: /* sorted already */ if (t.time <= now) { t.timeout_handler(); } else { timeout = t.time - now; break; } nevents = poll_function(events, timeout); for i in nevents: task t; if (events[i].type == READ) { t.handler = read_handler; } else { /* events[i].type == WRITE */ t.handler = write_handler; } run_tasks_add(t); } NGINX supports several I/O models (select, poll, kqueue, epoll, rtsig, /dev/poll, eventport). On Linux, epoll is the most efficient because it only notifies about active sockets. FastCGI and PHP‑FPM Integration FastCGI separates the web server from script interpreters. NGINX forwards .php requests to a FastCGI upstream (usually PHP‑FPM) via a Unix or TCP socket. Typical FastCGI configuration snippet: location ~ \.php$ { root html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name; } PHP‑FPM is a built‑in FastCGI process manager that replaces the older spawn‑fcgi . It provides better performance, smoother reloads, and finer control over process limits. Configuration Best Practices Avoid defining index inside location blocks; place it in the server context so all locations inherit it. Use try_files instead of if for existence checks. try_files $uri $uri/ /index.php; Prefer fastcgi.conf over fastcgi_params because it correctly sets SCRIPT_FILENAME without risking duplicate directives. Performance Optimizations Compilation : disable debug ( -g ) and enable CPU‑specific optimizations ( --with-cc-opt='-O3' , --with-cpu-opt=amd64 ). TCMalloc : build NGINX with --with-google_perftools_module and configure a profiling directory: google_perftools_profiles /tmp/tcmalloc; Kernel Tuning (add to /etc/sysctl.conf ): net.ipv4.tcp_max_tw_buckets = 6000 net.ipv4.ip_local_port_range = 1024 65000 net.core.somaxconn = 262144 net.core.netdev_max_backlog = 262144 # … other TCP parameters … NGINX Settings : worker_processes auto; (usually one per CPU core). worker_connections 65535; (max concurrent connections). Enable gzip compression. Configure open_file_cache to cache file metadata. Adjust buffer sizes for proxy and FastCGI ( proxy_buffer_size , fastcgi_buffers , etc.). Use log buffering ( access_log /var/log/nginx/access.log buffer=64k flush=5m; ). Apply rate‑limiting directives ( limit_conn , limit_req , limit_rate ). Error Troubleshooting Common errors and fixes: 400 Bad Request : increase client_header_buffer_size and large_client_header_buffers . 413 Request Entity Too Large : set client_max_body_size and adjust PHP’s post_max_size / upload_max_filesize . 502 Bad Gateway : ensure the FastCGI backend is running, increase fastcgi_connect_timeout , and verify enough PHP‑FPM workers. 504 Gateway Timeout : raise upstream timeout values or reduce backend load. upstream sent too big header : increase proxy_buffer_size , proxy_buffers , or fastcgi_buffers . Security Vulnerability (PATH_INFO) NGINX can mistakenly pass a crafted URI such as /image.jpg/evil.php to FastCGI, causing the server to treat a non‑PHP file as PHP when cgi.fix_pathinfo=1 . Mitigation: Set cgi.fix_pathinfo=0 in php.ini . Explicitly deny requests where $fastcgi_script_name contains a second .php segment: if ($fastcgi_script_name ~ \.php$) { return 403; } These steps prevent arbitrary files from being executed as PHP, closing the vulnerability.
Wukong Talks Architecture
Explaining distributed systems and architecture through stories. Author of the "JVM Performance Tuning in Practice" column, open-source author of "Spring Cloud in Practice PassJava", and independently developed a PMP practice quiz mini-program.
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.