Mastering Nginx: From Basics to Advanced Load Balancing and Performance Tuning

This article provides a comprehensive overview of Nginx, covering its definition, advantages, application scenarios, request processing flow, high‑concurrency mechanisms, proxy types, directory layout, configuration directives, load‑balancing algorithms, rate‑limiting strategies, health checks, gzip compression, and best practices for deployment and scaling.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Mastering Nginx: From Basics to Advanced Load Balancing and Performance Tuning

What is Nginx?

Nginx is a lightweight web server and reverse proxy server. Because it uses little memory, starts very quickly, and handles high concurrency, it is widely used in Internet projects.
Nginx is a lightweight/high‑performance reverse‑proxy web server that supports HTTP, HTTPS, SMTP, POP3 and IMAP. It efficiently implements reverse proxy and load balancing, handling 20‑30 k concurrent connections (officially up to 50 k). Major Chinese sites such as Sina, NetEase, and Tencent use Nginx.

Nginx Advantages

Cross‑platform, simple configuration.

Non‑blocking, high‑concurrency: handles 20‑30 k concurrent connections, officially up to 50 k.

Low memory consumption: ten Nginx processes use only about 150 MB.

Low cost and open source.

High stability, very low crash probability.

Built‑in health‑check: if a backend server fails, Nginx removes it from the pool and redirects requests to healthy nodes.

Nginx Application Scenarios

HTTP server: can serve static web pages.

Virtual hosts: host multiple sites on a single machine.

Reverse proxy and load balancing: distribute traffic across a cluster of backend servers.

API gateway: can be used for security management and request interception.

How Does Nginx Process Requests?

server { # first Server block, represents an independent virtual host
    listen 80; # default HTTP port
    server_name localhost;
    location / {
        root html; # site root directory
        index index.html index.html;
    }
}

When Nginx starts, it parses the configuration, creates a listening socket, binds it to the specified IP and port, and begins listening.

It then forks multiple worker processes.

Worker processes compete for new connections. The first worker that accepts a connection creates an ngx_connection_t structure.

The worker sets read/write event handlers and adds events to exchange data with the client.

When either side closes the connection, the lifecycle ends.

How Does Nginx Achieve High Concurrency?

If a server uses one process (or thread) per request, the number of processes equals the concurrency level, leading to many processes waiting for network I/O.
Nginx’s asynchronous non‑blocking model uses the waiting time efficiently: processes become idle while waiting, so a few processes can handle massive concurrency.
In a blocking model, each request occupies a dedicated process; when a fifth request arrives while four processes are busy, it must wait. Nginx instead assigns a worker to handle the request only up to the point where it might block (e.g., waiting for an upstream response), then registers an event and returns to the pool.

This is why Nginx, as an event‑driven server, can serve many connections with only a few processes.

What Is a Forward Proxy?

A forward proxy sits between the client and the origin server. The client sends a request to the proxy specifying the target server; the proxy forwards the request to the origin and returns the content to the client.

Clients must use a forward proxy. Example: OpenVPN.

What Is a Reverse Proxy?

A reverse proxy accepts Internet connections, forwards them to internal servers, and returns the responses to the client, appearing to the client as a single server.

Reverse proxy hides the origin servers, providing security and simplifying deployment.

Advantages of a Reverse Proxy Server

It can hide the characteristics of the source servers, acting as an intermediate layer between the Internet and web servers, which improves security, especially for hosted services.

Nginx Directory Structure

tree /usr/local/nginx
/usr/local/nginx
├── client_body_temp
├── conf # configuration files
│   ├── fastcgi.conf
│   ├── fastcgi.conf.default
│   ├── fastcgi_params
│   ├── fastcgi_params.default
│   ├── koi-utf
│   ├── koi-win
│   ├── mime.types
│   ├── mime.types.default
│   ├── nginx.conf # main configuration file
│   ├── nginx.conf.default
│   ├── scgi_params
│   ├── scgi_params.default
│   ├── uwsgi_params
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp
├── html # default site
│   ├── 50x.html # error page
│   └── index.html
├── logs
│   ├── access.log
│   ├── error.log
│   └── nginx.pid
├── proxy_temp
├── sbin
│   └── nginx # executable
├── scgi_temp
└── uwsgi_temp

Key Directives in nginx.conf

worker_processes 1; # number of worker processes
events {
    worker_connections 1024; # max connections per worker
}
http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    server {
        listen 80;
        server_name localhost;
        location / {
            root html;
            index index.html index.htm;
        }
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root html;
        }
    }
    ...
}

Cookie vs Session

Common

Both store user information as key‑value pairs.

Differences

Cookie

Stored in the client browser.

One cookie per domain; cannot be accessed across domains.

User can view or modify.

Set via HTTP response headers.

Acts as a key to unlock resources.

Session

Stored on the server (files, database, Redis).

Usually holds sensitive data.

Acts as a lock.

Why Doesn’t Nginx Use Multiple Threads?

Apache creates many processes or threads, each consuming CPU and memory; high concurrency exhausts resources.

Nginx uses a single‑threaded asynchronous non‑blocking model (epoll). It does not allocate CPU or memory per request, saving resources and reducing context switches, thus supporting higher concurrency.

Differences Between Nginx and Apache

Lightweight, lower memory and resource usage.

Asynchronous non‑blocking handling vs. Apache’s blocking model; Nginx maintains low resource consumption under high load.

Highly modular design; modules are easier to develop.

Core difference: Apache uses a synchronous multi‑process model (one connection per process), while Nginx is event‑driven (multiple connections per process).

Dynamic vs. Static Resource Separation

Separate unchanging static resources from frequently changing dynamic resources, allowing static assets to be cached.

Static files (HTML, JS, CSS, images) are served directly by Nginx, while dynamic requests are proxied to backend servers such as Tomcat.

Why Perform Static/Dynamic Separation?

Backend processing is unnecessary for static files. By separating, static assets can be cached (e.g., via CDN), reducing backend load and improving response speed.

What Is a CDN?

A Content Delivery Network distributes content to edge nodes close to users, increasing speed and providing larger bandwidth than a single origin server.

How Does Nginx Implement Static/Dynamic Separation?

Specify a directory for static files using a location block.
location /image/ {
    root /usr/local/static/;
    autoindex on;
}
# create directory
mkdir -p /usr/local/static/image
# upload files, then reload
sudo nginx -s reload

Access via http://server_name/image/1.jpg.

Nginx Load‑Balancing Algorithms and Strategies

Load balancing distributes traffic across a server pool to avoid overload.

Five common strategies:

1. Round‑Robin (default)

upstream backserver {
    server 192.168.0.12;
    server 192.168.0.13;
}

2. Weight

# higher weight = higher probability
upstream backserver {
    server 192.168.0.12 weight=2;
    server 192.168.0.13 weight=8;
}

3. ip_hash (IP binding)

upstream backserver {
    ip_hash;
    server 192.168.0.12:88;
    server 192.168.0.13:80;
}

4. fair (third‑party module)

upstream backserver {
    server server1;
    server server2;
    fair;
}

5. url_hash (third‑party module)

upstream backserver {
    server squid1:3128;
    server squid2:3128;
    hash $request_uri;
    hash_method crc32;
}

How to Solve Front‑End Cross‑Domain Issues with Nginx

Proxy cross‑origin API requests through Nginx, making the client think it is accessing the same origin.

Configuring Nginx Virtual Hosts

Three types:

Domain‑based virtual host (external website).

Port‑based virtual host (internal admin panels).

IP‑based virtual host.

Domain‑based Example

# www.example.com -> /data/www
server {
    listen 80;
    server_name www.example.com;
    location / {
        root data/www;
        index index.html index.htm;
    }
}
# bbs.example.com -> /data/bbs
server {
    listen 80;
    server_name bbs.example.com;
    location / {
        root data/bbs;
        index index.html index.htm;
    }
}

Port‑based Example

# www.example.com on port 8080
server {
    listen 8080;
    server_name 8080.example.com;
    location / {
        root data/www;
        index index.html index.htm;
    }
}
# Proxy 80 to 8080 backend
server {
    listen 80;
    server_name www.example.com;
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

Purpose of the location Directive

The location directive matches the request URI and applies specific actions such as serving files, proxying, or returning responses.

Note: "~" indicates a regular‑expression match.

Location Regular‑Expression Examples

# Exact match for root
location = / { return 400; }
# Prefix match (case‑sensitive)
location ^~ /av { root /data/av/; }
# Case‑sensitive regex
location ~ /media { alias /data/static/; }
# Case‑insensitive regex for static assets
location ~* .*(jpg|gif|png|js|css)$ { root /data/av/; }
# General fallback
location / { return 403; }

Rate Limiting (Limiting Requests)

Nginx can limit request speed to protect the server.

Three types:

Normal request rate limiting.

Burst request rate limiting.

Concurrent connection limiting.

All use the leaky‑bucket algorithm.

Implementation of three limiting algorithms.

1. Normal Rate Limiting

Limit each user to a certain request rate.

# Define a zone: 1 request per minute per IP
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/m;
server {
    location /seckill.html {
        limit_req zone=one;
        proxy_pass http://lj_seckill;
    }
}

2. Burst Rate Limiting

Allow short bursts beyond the normal rate.

# Same zone definition
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/m;
server {
    location /seckill.html {
        limit_req zone=one burst=5 nodelay;
        proxy_pass http://lj_seckill;
    }
}
With burst=5 nodelay , the first five requests are processed immediately; excess requests are delayed or dropped.

3. Concurrent Connection Limiting

http {
    limit_conn_zone $binary_remote_addr zone=myip:10m;
    limit_conn_zone $server_name zone=myServerName:10m;
}
server {
    location / {
        limit_conn myip 10;          # max 10 connections per IP
        limit_conn myServerName 100; # max 100 connections for the server
        rewrite / http://www.lijie.net permanent;
    }
}

Both leaky‑bucket and token‑bucket algorithms are used for rate limiting.

Leaky Bucket vs. Token Bucket

Leaky Bucket

Requests are water entering a bucket; the bucket leaks at a constant rate. If incoming rate exceeds leak rate, excess requests are dropped.

Token Bucket

A token is added to the bucket at a fixed rate. A request can proceed only if a token is available; otherwise it is rejected.

Tokens are consumed by requests; the bucket capacity and token rate control the flow.

High Availability Configuration

If an upstream server fails or is unresponsive, Nginx automatically fails over to the next server.
server {
    listen 80;
    server_name www.lijie.com;
    location / {
        proxy_pass http://backServer;
        proxy_connect_timeout 1s;
        proxy_send_timeout 1s;
        proxy_read_timeout 1s;
        index index.html index.htm;
    }
}

Blocking Specific IP Addresses

# Return 403 for a specific IP
if ($remote_addr = 192.168.9.115) {
    return 403;
}

Reject Requests from Certain Browsers

# Return 500 for Chrome browsers
if ($http_user_agent ~ Chrome) {
    return 500;
}

Health Checks for Backend Services

Two methods:

Use built‑in ngx_http_proxy_module and ngx_http_upstream_module health checks.

Use the third‑party nginx_upstream_check_module (recommended).

Enabling Gzip Compression

Gzip reduces the size of static resources, saving bandwidth and improving load speed, at the cost of some CPU.

http {
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 2;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
    gzip_vary on;
}

After enabling, static files such as jQuery shrink from 90 KB to about 30 KB.

When Not to Enable Gzip

Images (already compressed).

Very large files (CPU overhead outweighs benefit).

What Is the C10K Problem?

The C10K problem refers to the difficulty of handling 10,000 simultaneous network connections.

Does Nginx Support Compressing Requests to Upstream?

Yes, the gunzip module can decompress gzip‑encoded responses before forwarding them upstream.

Obtaining the Current Time in Nginx

proxy_set_header THE-TIME $date_gmt;

What Does the -s Option Do?

It sends signals to the Nginx master process (e.g., reload, stop, quit).

Adding Modules to Nginx

Modules must be selected at compile time; Nginx does not support dynamic module loading.

Setting the Number of Worker Processes in Production

On multi‑CPU systems, set worker_processes to the number of CPU cores. On a single‑CPU system, one worker is sufficient.

Nginx Status Codes

499 : Client closed the connection before the server responded.

502 : Bad gateway – possible causes include FastCGI not running, insufficient FastCGI workers, long execution time, insufficient buffers, or upstream timeout. Adjust timeouts and buffer sizes as needed.

# FastCGI timeout settings
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
# FastCGI buffer settings
fastcgi_buffer_size 32k;
fastcgi_buffers 8 32k;
# Proxy buffer settings
proxy_buffer_size 16k;
proxy_buffers 4 16k;
For PHP, increase the request_terminate_timeout in php-fpm.conf to avoid premature termination.

---

Original source: blog.csdn.net/wuzhiwei549/article/details/122758937
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

performanceload balancinghigh concurrencyreverse proxy
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.