Backend Development 33 min read

Mastering Nginx: From Basics to High‑Performance Load Balancing

This comprehensive guide explains what Nginx is, its advantages, deployment scenarios, request processing, high‑concurrency mechanisms, proxy types, directory layout, configuration directives, cookie vs session, threading model, load‑balancing algorithms, rate limiting, health checks, compression, and practical examples for building robust, scalable web services.

Open Source Linux
Open Source Linux
Open Source Linux
Mastering Nginx: From Basics to High‑Performance Load Balancing

What is Nginx?

Nginx is a lightweight, high‑performance reverse‑proxy web server that supports HTTP, HTTPS, SMTP, POP3 and IMAP protocols. It provides efficient reverse proxying and load balancing, handling 20‑30 k concurrent connections (officially up to 50 k), and is used by many Chinese sites such as Sina, NetEase and Tencent.

Advantages of Nginx

Cross‑platform and easy to configure.

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

Low memory usage: ten Nginx processes consume only about 150 MB.

Low cost and open source.

High stability with very low crash probability.

Built‑in health‑check: failed servers are automatically bypassed.

Nginx Application Scenarios

HTTP server – can serve static web pages.

Virtual hosting – multiple sites on a single server.

Reverse proxy and load balancing – distribute traffic across a cluster when a single server is insufficient.

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

How Nginx Processes Requests

server {          # first Server block – a virtual host
    listen 80;   # listening port (default 80)
    server_name localhost;
    location / {
        root html;               # site root directory
        index index.html index.html; # default index files
    }
}

On startup Nginx parses the configuration, creates a listening socket, and binds it to the specified IP and port.

It then forks multiple worker processes.

Workers compete for new connections; the successful worker accepts the socket and creates an

ngx_connection_t

structure.

The worker sets read/write event handlers and exchanges data with the client.

When either side closes the connection, the lifecycle ends.

How Nginx Achieves High Concurrency

Nginx uses an asynchronous, non‑blocking event model (epoll). A worker handles many requests by processing only the parts that may block (e.g., upstream communication) and otherwise stays idle, allowing a few workers to serve massive concurrency.

What Is a Forward Proxy?

A forward proxy sits between the client and the origin server; the client sends a request to the proxy, which forwards it to the origin and returns the response. It proxies on behalf of the client.

What Is a Reverse Proxy?

A reverse proxy receives Internet requests, forwards them to internal servers, and returns the responses to the client, acting as the external entry point for backend services.

Reverse proxy in one sentence: it proxies on behalf of the server.

Advantages of a Reverse Proxy Server

It hides the existence and characteristics of origin servers, providing an additional security layer between the Internet and backend web servers.

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
│   ├── nginx.conf.default
│   ├── scgi_params
│   ├── scgi_params.default
│   ├── uwsgi_params
│   ├── uwsgi_params.default
│   └── win-utf
├── fastcgi_temp
├── html                     # default site
│   ├── 50x.html
│   └── 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.

Cookie:

Stored in the client browser.

One cookie per domain; cannot be accessed across domains.

Client can view or modify.

Set via HTTP response headers.

Session:

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

Can hold sensitive data.

Why Nginx Does Not Use Multithreading

Apache creates multiple processes or threads, each consuming CPU and memory. Nginx uses a single‑threaded asynchronous non‑blocking model (epoll) with configurable worker processes, avoiding per‑request thread allocation and reducing context switches, thus supporting higher concurrency.

Nginx vs Apache

Nginx is lightweight, uses less memory, and handles requests asynchronously, while Apache is synchronous and creates a process per connection. Nginx’s modular design makes module development simpler.

Dynamic vs Static Resource Separation

Separating dynamic and static resources allows static files to be cached, improving response speed. Static files (CSS, JS, images) are served directly, while dynamic requests are forwarded to application servers.

Why Perform Dynamic/Static Separation?

Static files do not require backend processing, reducing load on application servers and speeding up content delivery. CDN services can further accelerate static asset delivery.

What Is a CDN Service?

A Content Delivery Network places copies of content on edge nodes close to users, reducing latency and bandwidth usage.

How Nginx Implements Dynamic/Static Separation

Define a location that maps a URL path to a directory on disk.

location /image/ {
    root /usr/local/static/;
    autoindex on;
}
# Create directory
mkdir /usr/local/static/image
# Upload files, then reload Nginx
sudo nginx -s reload
# Access via http://server_name/image/1.jpg

Nginx Load‑Balancing Algorithms and Strategies

Nginx provides several load‑balancing methods:

Round‑robin (default) – distributes requests sequentially.

upstream backserver {
    server 192.168.0.12;
    server 192.168.0.13;
}

Weight – servers with higher weight receive more traffic.

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

IP hash – same client IP is routed to the same backend.

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

Fair (third‑party module) – prefers servers with faster response times.

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

URL hash (third‑party module) – hashes the request URI.

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

Solving Front‑End Cross‑Origin with Nginx

Configure Nginx to proxy cross‑origin API endpoints as same‑origin requests.

Nginx Virtual Host Configuration

Domain‑based virtual host – separate sites by domain name.

Port‑based virtual host – separate sites by listening port.

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 → /data/www
server {
    listen 8080;
    server_name 8080.example.com;
    location / {
        root data/www;
        index index.html index.htm;
    }
}
# Proxy port 80 to backend 127.0.0.1:8080
server {
    listen 80;
    server_name www.example.com;
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

Purpose of the location Directive

The

location

block matches request URIs and applies specific configuration (root, proxy, etc.). Syntax examples include exact match (=), prefix (^~), case‑sensitive regex (~), and case‑insensitive regex (~*).

Rate Limiting in Nginx

Three types of rate limiting based on the leaky‑bucket algorithm:

Normal request rate limiting.

Burst limiting for sudden spikes.

Concurrent connection limiting.

Normal Rate Limiting

# Allow 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;
    }
}

Burst Limiting

# Allow bursts of up to 5 requests without delay
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;
    }
}

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;
        limit_conn myServerName 100;
    }
}

Leaky Bucket and Token Bucket Algorithms

Leaky Bucket

Requests are treated as water entering a bucket; the bucket drains at a fixed rate. If incoming rate exceeds drain rate, excess requests are dropped.

Token Bucket

A token is added to a bucket at a constant rate. A request can proceed only if a token is available; otherwise it is rejected. Controlling bucket size and token rate limits traffic.

High Availability Configuration

Configure upstream servers with health checks and set appropriate timeouts so that if a backend fails, Nginx automatically fails over to another server.

server {
    listen 80;
    server_name www.example.com;
    location / {
        proxy_pass http://backServer;
        proxy_connect_timeout 1s;
        proxy_send_timeout 1s;
        proxy_read_timeout 1s;
    }
}

Blocking Specific IPs

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

Blocking Undefined Server Names

Define an empty server_name to match requests without a Host header and return a non‑standard response to terminate the connection.

Restricting Browser Access

# Block Chrome browsers with 500 error
if ($http_user_agent ~ Chrome) {
    return 500;
}

Rewrite Global Variables

Common Nginx variables include

$remote_addr

,

$host

,

$request_uri

,

$status

,

$http_user_agent

, etc., which can be used in rewrite rules and logging.

Backend Health Check

Two approaches: using built‑in

ngx_http_proxy_module

and

ngx_http_upstream_module

, or the third‑party

nginx_upstream_check_module

for more advanced checks.

Enabling Compression

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 reloading Nginx, responses will include

Content‑Encoding: gzip

, reducing payload size.

Purpose of ngx_http_upstream_module

Defines server groups that can be referenced by

proxy_pass

,

fastcgi_pass

,

uwsgi_pass

,

memcached_pass

, and

scgi_pass

directives.

What Is the C10K Problem?

The inability of a server to handle ten thousand simultaneous network connections efficiently.

Can Nginx Compress Requests to Upstream?

Yes, the

gunzip

filter can decompress gzip‑encoded responses for upstream servers that do not support gzip.

Getting the Current Time in Nginx

proxy_set_header THE-TIME $date_gmt;

Purpose of the -s Option

Used to send signals (e.g., reload, stop, quit) to a running Nginx master process.

Adding Modules to Nginx

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

Setting Worker Processes in Production

Typically set the number of workers equal to the number of CPU cores. More workers than cores can cause context‑switch overhead.

Nginx Status Codes and Troubleshooting

Examples:

499 – client closed the connection before the server responded.

502 – Bad gateway; possible causes include FastCGI not started, insufficient FastCGI workers, long FastCGI execution time, buffer limits, or slow PHP scripts.

fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 32k;
fastcgi_buffers 8 32k;
proxy_buffer_size 16k;
proxy_buffers 4 16k;
Load Balancingconfigurationhigh concurrencynginxReverse ProxyWeb ServerRate Limiting
Open Source Linux
Written by

Open Source Linux

Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.

0 followers
Reader feedback

How this landed with the community

login 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.