Back to blog

Reverse Proxy Giải Thích Chi Tiết

reverse-proxyinfrastructuredevopsbackendnetworkingnginx
Reverse Proxy Giải Thích Chi Tiết

Mọi web application trên production đều nằm sau một reverse proxy. Có thể bạn không nhận ra, nhưng nếu đã deploy lên Vercel, AWS, hay bất kỳ cloud provider nào — có một reverse proxy giữa users và code của bạn.

Trong bài Load Balancing, chúng ta đã nói về việc phân phối traffic qua nhiều servers. Reverse proxy làm nhiều hơn thế — nó là cánh cửa chính vào toàn bộ backend, xử lý SSL, caching, security, routing, và đương nhiên cả load balancing nữa.

Thời gian: 1-2 giờ
Điều kiện: Hiểu cơ bản về HTTP và kiến trúc client-server

Những Gì Bạn Sẽ Học

✅ Reverse proxy là gì và khác forward proxy như thế nào
✅ Cách reverse proxy hoạt động — request flow đầy đủ
✅ SSL/TLS termination — chuyển việc mã hóa ra khỏi application
✅ Caching — trả response mà không cần đụng backend
✅ Security benefits — ẩn servers, chặn attacks, rate limit
✅ Load balancing — phân phối traffic với reverse proxy
✅ WebSocket và gRPC proxying — hỗ trợ real-time protocols
✅ Setup thực tế — cấu hình Nginx, Traefik, và Caddy


1. Reverse Proxy Là Gì?

Reverse proxy nằm giữa clients và backend servers. Clients không bao giờ nói chuyện trực tiếp với servers — họ nói với proxy, và proxy forward requests tới đúng server.

Điểm mấu chốt: clients không biết server nào xử lý request. Họ chỉ thấy IP address của reverse proxy. Concept đơn giản này enable mọi thứ khác — SSL termination, caching, load balancing, security.

Nó Thực Sự Làm Gì

Khi request đến reverse proxy:

  1. Nhận HTTP request từ client
  2. Kiểm tra request (URL path, headers, method)
  3. Quyết định backend server nào xử lý
  4. Forward request tới server đó
  5. Nhận response từ backend
  6. Trả response cho client

Client nghĩ mình đang nói chuyện với một server. Thực tế, có thể có hàng chục servers phía sau proxy.


2. Forward Proxy vs Reverse Proxy

Hai khái niệm này hay bị nhầm. Chúng nằm ở hai phía đối lập của connection.

Khía CạnhForward ProxyReverse Proxy
Bảo vệClientsServers
Ai dùngPhía client (mạng công ty, VPN)Phía server (web infrastructure)
Client biết khôngCó (cấu hình trong browser/OS)Không (transparent)
Server biết khôngKhông (thấy IP của proxy)Có (cấu hình để nhận từ proxy)
Mục đích chínhAccess control, anonymity, cachingSecurity, performance, routing
Ví dụSquid, corporate firewalls, VPNNginx, Traefik, Cloudflare

Forward proxy: Proxy của công ty bạn filter web traffic. Bạn cấu hình browser để dùng nó. Website không biết bạn đang sau proxy.

Reverse proxy: Nginx ngồi trước Node.js app. Users không biết nó tồn tại. Node.js app biết requests đến thông qua nó.


3. Tại Sao Dùng Reverse Proxy?

Bạn có thể expose application trực tiếp ra internet. Đây là lý do không nên:

Security

Application servers ẩn trên private network. Attackers không thể truy cập trực tiếp.

Không có reverse proxy:
Internet → App Server (public IP, exposed ports, vulnerable)
 
Có reverse proxy:
Internet → Reverse Proxy (public IP) → App Server (private network)

Reverse proxy là gateway được hardened, build chuyên dụng. Application server thoải mái focus vào business logic mà không lo DDoS protection, rate limiting, hay IP filtering.

Performance

  • SSL termination: Xử lý encryption ở proxy, không phải app
  • Caching: Trả cached responses mà không đụng backend
  • Compression: Gzip/Brotli responses trước khi gửi cho clients
  • Connection pooling: Tái sử dụng backend connections thay vì tạo mới
  • Static file serving: Để proxy serve images, CSS, JS trực tiếp

Flexibility

  • Zero-downtime deploys: Swap backend servers mà không drop connections
  • A/B testing: Route traffic tới các app versions khác nhau
  • API gateway: Route /api/* tới một service, /web/* tới service khác
  • Protocol translation: Nhận HTTP/2 từ clients, nói HTTP/1.1 với backends

4. Cách Reverse Proxy Hoạt Động

Hãy trace một request hoàn chỉnh qua reverse proxy:

Hành Trình Của Request

Bước 1 — SSL Termination: Proxy decrypt HTTPS request. Backend servers nhận plain HTTP trên private network.

Bước 2 — Cache Check: Nếu response đã được cache và còn fresh, trả về ngay. Backend không bao giờ thấy request này.

Bước 3 — Rate Limiting: Kiểm tra xem client IP đã vượt quá request limits chưa. Nếu rồi, trả 429 Too Many Requests.

Bước 4 — Backend Selection: Chọn backend server (round robin, least connections, URL-based routing).

Bước 5 — Cache Storage: Nếu response từ backend có Cache-Control headers, lưu lại cho future requests.

Bước 6 — Compression: Nén response body bằng gzip hoặc Brotli trước khi gửi cho client.

Headers Được Proxy Thêm Vào

Reverse proxies thêm headers để backends biết thông tin request gốc:

X-Forwarded-For: 203.0.113.50          # IP thật của client
X-Forwarded-Proto: https               # Protocol gốc
X-Forwarded-Host: example.com          # Hostname gốc
X-Real-IP: 203.0.113.50                # Client IP (Nginx-specific)
X-Request-ID: abc-123-def              # Request identifier duy nhất

Không có headers này, backend sẽ thấy IP của proxy thay vì client IP — phá vỡ logging, rate limiting, và geolocation.


5. SSL/TLS Termination

SSL termination là lý do phổ biến nhất để dùng reverse proxy. Nó chuyển việc encryption ra khỏi application.

Tại Sao Terminate Ở Proxy?

Không Có ProxyCó Proxy
Mỗi app server cần SSL certificatesMột certificate trên proxy
App xử lý TLS handshakes (tốn CPU)Proxy xử lý toàn bộ TLS
Renew certificate trên mỗi serverRenew một lần, một chỗ
App frameworks cần SSL configurationApp chạy plain HTTP
Mixed protocols phức tạp hơnHTTP nội bộ sạch sẽ

Nginx SSL Termination

server {
    listen 443 ssl http2;
    server_name example.com;
 
    # SSL certificates
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 
    # Modern TLS configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
 
    # HSTS (bảo browsers luôn dùng HTTPS)
    add_header Strict-Transport-Security "max-age=63072000" always;
 
    # Proxy tới backend (plain HTTP)
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
 
# Redirect HTTP sang HTTPS
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}

Các SSL Modes

SSL Termination:

SSL Passthrough:

SSL Re-encryption:

ModeClient → ProxyProxy → BackendUse Case
TerminationHTTPSHTTPPhổ biến nhất. Backend trên private network
PassthroughHTTPSHTTPS (cùng connection)Proxy không inspect traffic. End-to-end encryption
Re-encryptionHTTPSHTTPS (connection mới)Compliance requirements. Proxy inspect + re-encrypt

Với hầu hết applications, SSL termination là lựa chọn đúng. Backend chạy trên private network nơi HTTP là đủ.


6. Caching

Reverse proxy có thể cache responses và serve mà không cần đụng backend. Đây là performance win lớn nhất cho read-heavy applications.

Cách Hoạt Động

Cấu Hình Nginx Caching

# Define cache zone (10MB metadata, 1GB storage, 60 phút hết hạn)
proxy_cache_path /var/cache/nginx levels=1:2
    keys_zone=app_cache:10m
    max_size=1g
    inactive=60m
    use_temp_path=off;
 
server {
    listen 443 ssl http2;
    server_name example.com;
 
    location /api/ {
        proxy_pass http://backend;
 
        # Bật caching
        proxy_cache app_cache;
        proxy_cache_valid 200 10m;       # Cache response 200 trong 10 phút
        proxy_cache_valid 404 1m;        # Cache response 404 trong 1 phút
        proxy_cache_use_stale error timeout updating;  # Serve stale khi error
        proxy_cache_lock on;             # Chỉ 1 request tới backend cho cùng URL
 
        # Cache key (gì tạo nên mỗi cached entry duy nhất)
        proxy_cache_key "$scheme$request_method$host$request_uri";
 
        # Thêm cache status header để debug
        add_header X-Cache-Status $upstream_cache_status;
    }
 
    # Không cache POST, PUT, DELETE
    location /api/ {
        if ($request_method != GET) {
            set $no_cache 1;
        }
        proxy_cache_bypass $no_cache;
        proxy_no_cache $no_cache;
    }
 
    # Cache static assets mạnh tay
    location /static/ {
        proxy_pass http://backend;
        proxy_cache app_cache;
        proxy_cache_valid 200 7d;        # 7 ngày cho static files
        add_header Cache-Control "public, max-age=604800";
    }
}

Cache Status Headers

Header X-Cache-Status cho biết chuyện gì xảy ra:

StatusÝ Nghĩa
HITServe từ cache
MISSKhông có trong cache, forward tới backend
EXPIREDCó trong cache nhưng hết hạn, fetch lại
STALECache hết hạn nhưng serve stale (backend đang down)
BYPASSCache bị bypass (POST, cookie-based, v.v.)
UPDATINGServe stale trong khi update ở background

Nên Cache Gì, Không Nên Cache Gì

CacheKhông Cache
API responses có Cache-Control headersUser-specific data (profile, cart, settings)
Static assets (CSS, JS, images, fonts)Responses có Set-Cookie
Public content (blog posts, product listings)POST/PUT/DELETE requests
Search results (với short TTL)Real-time data (stock prices, chat)
Third-party API responsesAuthenticated API responses

7. Load Balancing với Reverse Proxy

Hầu hết reverse proxies đi kèm load balancing. Chúng ta đã cover algorithms chi tiết trong bài Load Balancing — đây là setup thực tế.

Nginx Load Balancing

# Define backend server group
upstream api_servers {
    least_conn;                         # Dùng least connections algorithm
 
    server 10.0.1.101:3000 weight=3;   # Server mạnh hơn nhận nhiều traffic hơn
    server 10.0.1.102:3000 weight=2;
    server 10.0.1.103:3000 weight=1;
    server 10.0.1.104:3000 backup;     # Chỉ dùng khi các server khác down
 
    # Health checks (Nginx Plus)
    # health_check interval=10 fails=3 passes=2;
}
 
server {
    listen 443 ssl http2;
    server_name api.example.com;
 
    location / {
        proxy_pass http://api_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 
        # Timeouts
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
        proxy_send_timeout 10s;
 
        # Retry on failure
        proxy_next_upstream error timeout http_502 http_503;
        proxy_next_upstream_tries 2;
    }
}

Path-Based Routing

Route các paths khác nhau tới các backend services khác nhau:

upstream web_app {
    server 10.0.1.101:3000;
    server 10.0.1.102:3000;
}
 
upstream api_service {
    server 10.0.2.101:8080;
    server 10.0.2.102:8080;
}
 
upstream admin_panel {
    server 10.0.3.101:4000;
}
 
server {
    listen 443 ssl http2;
    server_name example.com;
 
    # Frontend application
    location / {
        proxy_pass http://web_app;
    }
 
    # API service
    location /api/ {
        proxy_pass http://api_service;
    }
 
    # Admin panel (giới hạn bởi IP)
    location /admin/ {
        allow 10.0.0.0/8;
        deny all;
        proxy_pass http://admin_panel;
    }
}

Đây là API gateway pattern — một entry point duy nhất routing tới nhiều services dựa trên URL path, headers, hoặc các request attributes khác.


8. Security Benefits

Reverse proxy là tuyến phòng thủ đầu tiên. Đây là những gì nó làm được:

Ẩn Backend Servers

Expose trực tiếp:
Client → App Server tại 203.0.113.10:3000
(Attacker biết server IP, port, và technology)
 
Sau reverse proxy:
Client → Proxy tại 198.51.100.1:443
(Attacker chỉ thấy proxy. Backend trên private 10.x.x.x network)

Proxy chỉ expose ports 80 và 443. Application servers vô hình với internet.

Rate Limiting

# Define rate limit zone (10MB shared memory, 10 requests/giây mỗi IP)
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=1r/s;
 
server {
    # API endpoints — 10 req/s với burst 20
    location /api/ {
        limit_req zone=api_limit burst=20 nodelay;
        proxy_pass http://backend;
    }
 
    # Login endpoint — strict 1 req/s
    location /api/auth/login {
        limit_req zone=login_limit burst=3;
        limit_req_status 429;
        proxy_pass http://backend;
    }
}

Request Filtering

Chặn suspicious requests trước khi chúng tới application:

server {
    # Chặn known bad user agents
    if ($http_user_agent ~* (bot|crawler|spider|scraper)) {
        return 403;
    }
 
    # Chặn requests có SQL injection patterns
    location /api/ {
        if ($query_string ~* "(union|select|insert|update|delete|drop)") {
            return 403;
        }
        proxy_pass http://backend;
    }
 
    # Chặn request bodies quá lớn (ngăn upload attacks)
    client_max_body_size 10m;
 
    # Ẩn server version
    server_tokens off;
 
    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}

IP Allowlisting

# Admin endpoints chỉ truy cập được từ IPs cụ thể
location /admin/ {
    allow 10.0.0.0/8;       # Internal network
    allow 192.168.1.0/24;   # Office network
    deny all;               # Chặn tất cả
    proxy_pass http://admin_backend;
}

9. WebSocket và gRPC Proxying

Reverse proxies xử lý nhiều hơn HTTP. Applications hiện đại cần WebSocket và gRPC support.

WebSocket Proxying

WebSocket connections bắt đầu là HTTP rồi upgrade. Proxy cần handle việc upgrade này:

# WebSocket support
map $http_upgrade $connection_upgrade {
    default upgrade;
    ""      close;
}
 
server {
    listen 443 ssl http2;
    server_name example.com;
 
    # WebSocket endpoint
    location /ws/ {
        proxy_pass http://websocket_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_set_header Host $host;
 
        # Timeouts dài hơn cho WebSocket connections
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }
 
    # HTTP thông thường
    location / {
        proxy_pass http://web_backend;
    }
}

Settings quan trọng:

  • proxy_http_version 1.1 — WebSocket yêu cầu HTTP/1.1
  • Upgrade và Connection headers — bảo backend upgrade
  • Timeouts dài — WebSocket connections tồn tại lâu

gRPC Proxying

server {
    listen 443 ssl http2;
    server_name grpc.example.com;
 
    location / {
        grpc_pass grpc://grpc_backend;
        grpc_set_header Host $host;
 
        # Error handling
        error_page 502 = /error502grpc;
    }
 
    location = /error502grpc {
        internal;
        default_type application/grpc;
        add_header grpc-status 14;
        add_header content-length 0;
        return 204;
    }
}

10. Request/Response Manipulation

Reverse proxies có thể modify requests và responses khi chúng đi qua.

URL Rewriting

server {
    # Rewrite /old-api/* thành /api/v2/*
    location /old-api/ {
        rewrite ^/old-api/(.*) /api/v2/$1 break;
        proxy_pass http://backend;
    }
 
    # Strip prefix: /service-a/users → /users
    location /service-a/ {
        proxy_pass http://service_a_backend/;  # Trailing slash strip prefix
    }
 
    # Add prefix: /users → /api/v1/users
    location /users {
        proxy_pass http://backend/api/v1/users;
    }
}

Header Manipulation

server {
    location /api/ {
        proxy_pass http://backend;
 
        # Thêm headers vào request gửi tới backend
        proxy_set_header X-Request-ID $request_id;
        proxy_set_header X-Real-IP $remote_addr;
 
        # Thêm headers vào response gửi cho client
        add_header X-Served-By $hostname;
        add_header X-Response-Time $request_time;
 
        # Xóa sensitive headers từ backend response
        proxy_hide_header X-Powered-By;
        proxy_hide_header Server;
    }
}

Response Compression

server {
    # Bật gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 5;
    gzip_types
        text/plain
        text/css
        text/javascript
        application/json
        application/javascript
        application/xml
        image/svg+xml;
 
    # Không nén files đã nén
    gzip_proxied any;
 
    location / {
        proxy_pass http://backend;
    }
}

11. Reverse Proxy Trong Microservices

Trong kiến trúc microservices, reverse proxy trở thành API gateway — single entry point cho tất cả client requests.

API Gateway Xử Lý Gì

Trách NhiệmVí Dụ
Routing/api/users/* → User Service
AuthenticationValidate JWT trước khi forward
Rate limiting100 req/phút mỗi API key
Request aggregationGom responses từ nhiều services
Protocol translationNhận REST, forward dạng gRPC
Circuit breakingNgừng forward tới failed services
LoggingAccess logs tập trung

Nginx Làm API Gateway

upstream auth_service {
    server 10.0.1.101:3001;
}
 
upstream user_service {
    server 10.0.2.101:3002;
    server 10.0.2.102:3002;
}
 
upstream order_service {
    server 10.0.3.101:3003;
    server 10.0.3.102:3003;
    server 10.0.3.103:3003;
}
 
server {
    listen 443 ssl http2;
    server_name api.example.com;
 
    # Auth subrequest — validate token trước khi forward
    location = /auth/validate {
        internal;
        proxy_pass http://auth_service/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
    }
 
    # Protected endpoints — yêu cầu auth
    location /api/users/ {
        auth_request /auth/validate;
        auth_request_set $auth_user $upstream_http_x_auth_user;
        proxy_set_header X-Auth-User $auth_user;
        proxy_pass http://user_service/;
    }
 
    location /api/orders/ {
        auth_request /auth/validate;
        auth_request_set $auth_user $upstream_http_x_auth_user;
        proxy_set_header X-Auth-User $auth_user;
        proxy_pass http://order_service/;
    }
 
    # Public endpoints — không cần auth
    location /api/auth/ {
        proxy_pass http://auth_service/;
    }
}

12. Các Reverse Proxy Solutions Phổ Biến

Nginx

Reverse proxy được dùng nhiều nhất. Xử lý hàng triệu concurrent connections với ít resources.

Phù hợp nhất cho: General-purpose reverse proxy, static file serving, SSL termination.

# Complete Nginx reverse proxy setup
server {
    listen 80;
    server_name example.com;
    return 301 https://$server_name$request_uri;
}
 
server {
    listen 443 ssl http2;
    server_name example.com;
 
    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 
    # Security
    server_tokens off;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
 
    # Compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript;
 
    # Proxy tới backend
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
 
        # Timeouts
        proxy_connect_timeout 5s;
        proxy_read_timeout 60s;
    }
 
    # Static files
    location /static/ {
        alias /var/www/static/;
        expires 7d;
        add_header Cache-Control "public, immutable";
    }
}

Traefik

Thiết kế cho containerized environments. Tự động phát hiện services từ Docker và Kubernetes.

Phù hợp nhất cho: Docker Compose, Kubernetes, dynamic service discovery.

# docker-compose.yml với Traefik
version: "3.8"
 
services:
  traefik:
    image: traefik:v3.0
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "[email protected]"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"    # Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt
 
  api:
    image: my-api:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.example.com`)"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      - "traefik.http.services.api.loadbalancer.server.port=3000"
    deploy:
      replicas: 3
 
  web:
    image: my-web:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.web.rule=Host(`example.com`)"
      - "traefik.http.routers.web.tls.certresolver=letsencrypt"
      - "traefik.http.services.web.loadbalancer.server.port=8080"
 
volumes:
  letsencrypt:

Siêu năng lực của Traefik: không cần config files cho routing. Thêm Docker labels vào services, Traefik tự động tạo routes, SSL certificates, và load balancing.

Caddy

Reverse proxy đơn giản nhất. Automatic HTTPS không cần cấu hình gì.

Phù hợp nhất cho: Deployments nhỏ đến trung bình khi simplicity quan trọng nhất.

# Caddyfile — đây là toàn bộ configuration
example.com {
    reverse_proxy 127.0.0.1:3000
 
    # Automatic HTTPS — Caddy xử lý certificates
    # Automatic HTTP → HTTPS redirect
    # Automatic certificate renewal
}
 
api.example.com {
    reverse_proxy /api/users/* 10.0.1.101:3001 10.0.1.102:3001 {
        lb_policy least_conn
        health_uri /health
        health_interval 10s
    }
 
    reverse_proxy /api/orders/* 10.0.2.101:3002
 
    # Compression
    encode gzip
 
    # Rate limiting
    rate_limit {
        zone api {
            key {remote_host}
            events 100
            window 1m
        }
    }
}

So Sánh

FeatureNginxTraefikCaddy
ConfigurationConfig filesLabels/APICaddyfile
Auto HTTPSManual (certbot)Built-inBuilt-in
Docker integrationManualAutomaticPlugin
PerformanceExcellentGoodGood
Learning curveModerateLow (Docker)Very low
EcosystemHugeGrowingGrowing
Phù hợp nhấtProduction at scaleContainersSimple deployments

13. Performance Optimization

Connection Pooling

Không có connection pooling, mỗi request tạo TCP connection mới tới backend:

Client → Proxy → [TCP connection mới] → Backend → [đóng] → Proxy → Client
Client → Proxy → [TCP connection mới] → Backend → [đóng] → Proxy → Client

Với keepalive connections:

Client → Proxy → [tái sử dụng connection] → Backend → Proxy → Client
Client → Proxy → [tái sử dụng connection] → Backend → Proxy → Client
upstream backend {
    server 10.0.1.101:3000;
    server 10.0.1.102:3000;
 
    # Giữ 32 idle connections sống mỗi worker
    keepalive 32;
}
 
server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";  # Bật keepalive tới upstream
    }
}

Buffering

Control cách proxy buffer responses từ backends:

server {
    location /api/ {
        proxy_pass http://backend;
 
        # Buffer backend response
        proxy_buffering on;
        proxy_buffer_size 4k;        # Buffer cho phần đầu response
        proxy_buffers 8 16k;         # 8 buffers mỗi cái 16k
        proxy_busy_buffers_size 32k; # Max size trước khi gửi cho client
    }
 
    # Tắt buffering cho streaming endpoints
    location /api/stream/ {
        proxy_pass http://backend;
        proxy_buffering off;
    }
}

Timeouts

Set timeouts phù hợp để tránh hanging connections:

server {
    # Thời gian thiết lập connection tới backend
    proxy_connect_timeout 5s;
 
    # Thời gian đọc response từ backend
    proxy_read_timeout 60s;
 
    # Thời gian gửi request tới backend
    proxy_send_timeout 10s;
 
    # Client request body timeout
    client_body_timeout 10s;
 
    # Client response timeout
    send_timeout 10s;
 
    # Keep-alive timeout
    keepalive_timeout 65s;
}

14. Common Patterns

Blue-Green Deployment

Switch traffic giữa hai environments giống nhau:

# Blue environment (đang live)
upstream blue {
    server 10.0.1.101:3000;
    server 10.0.1.102:3000;
}
 
# Green environment (version mới)
upstream green {
    server 10.0.2.101:3000;
    server 10.0.2.102:3000;
}
 
# Toggle bằng cách đổi upstream
server {
    location / {
        proxy_pass http://blue;   # Đổi thành "green" để switch
    }
}

Canary Deployment

Gửi một phần trăm traffic tới version mới:

upstream stable {
    server 10.0.1.101:3000 weight=9;
    server 10.0.1.102:3000 weight=9;
}
 
upstream canary {
    server 10.0.2.101:3000 weight=1;
}
 
# Split traffic dùng map
split_clients "${remote_addr}" $backend {
    90%   stable;
    *     canary;
}
 
server {
    location / {
        proxy_pass http://$backend;
    }
}

Health Check Endpoint

Backend nên expose health check endpoint cho proxy:

// Express.js health check
app.get("/health", (_req, res) => {
  const health = {
    status: "ok",
    uptime: process.uptime(),
    timestamp: new Date().toISOString(),
  };
 
  try {
    // Kiểm tra database connection
    // await db.query("SELECT 1");
    res.json(health);
  } catch (error) {
    res.status(503).json({
      ...health,
      status: "error",
      message: "Database connection failed",
    });
  }
});

15. Troubleshooting

Các Vấn Đề Thường Gặp

Vấn ĐềNguyên NhânCách Fix
502 Bad GatewayBackend down hoặc không respondKiểm tra backend health, tăng timeouts
504 Gateway TimeoutBackend quá chậmTăng proxy_read_timeout, optimize backend
WebSocket dropsThiếu upgrade headersThêm Upgrade và Connection headers
Sai client IPThiếu forwarded headersThêm X-Real-IP và X-Forwarded-For
Mixed contentSai X-Forwarded-ProtoSet proxy_set_header X-Forwarded-Proto $scheme
Upload lớn failclient_max_body_size quá nhỏTăng client_max_body_size
CORS errorsHeaders bị proxy stripThêm CORS headers trong proxy config

Debugging Checklist

  1. Check backend trực tiếp: curl http://127.0.0.1:3000 — có hoạt động không qua proxy?
  2. Check proxy logs: tail -f /var/log/nginx/error.log
  3. Check response headers: curl -I https://example.com — tìm X-Cache-Status, Server
  4. Test SSL: openssl s_client -connect example.com:443 — certificate chain OK?
  5. Check upstream health: curl http://backend:3000/health — backend healthy?

Tổng Kết

Chủ ĐềNhững Gì Đã Cover
ConceptReverse proxy nằm giữa clients và servers, xử lý routing, security, và performance
Forward vs ReverseForward bảo vệ clients, reverse bảo vệ servers
SSL TerminationChuyển encryption sang proxy, backends chạy plain HTTP
CachingCache responses ở proxy để giảm tải backend
SecurityẨn servers, rate limit, filter requests, thêm security headers
Load BalancingPhân phối traffic qua nhiều backend servers
WebSocket/gRPCXử lý connection upgrades và HTTP/2 streaming
API GatewayRoute requests tới các microservices khác nhau dựa trên path
SolutionsNginx (production), Traefik (containers), Caddy (simplicity)
PerformanceConnection pooling, compression, buffering, timeouts

Key takeaways:

✅ Mọi production application nên nằm sau reverse proxy
✅ SSL termination ở proxy đơn giản hóa certificate management
✅ Caching là performance win lớn nhất cho read-heavy apps
✅ Proxy là security layer đầu tiên — rate limiting, IP filtering, header security
✅ Path-based routing biến reverse proxy thành API gateway
✅ Bắt đầu với Nginx cho hầu hết use cases, Traefik cho Docker, Caddy cho simplicity
✅ Luôn set proper timeouts, forwarded headers, và health checks


Reverse proxy không chỉ là infrastructure plumbing — đó là nơi performance, security, và deployment flexibility hội tụ. Setup một lần, cấu hình cho tốt, và backend của bạn thoải mái focus vào điều quan trọng: application logic.

📬 Đăng ký nhận bản tin

Nhận những bài viết mới nhất qua email mỗi tuần. Không spam, hủy đăng ký bất cứ lúc nào.

Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất cứ lúc nào.

💬 Comments

Đăng nhập để bình luận

Chúng tôi sẽ không đăng bất cứ điều gì mà không có sự cho phép của bạn.