Nginx 高效能架構解析

techlead_krischang發表於2024-07-10

本文詳細探討了Nginx的反向代理、負載均衡和效能最佳化技術,包括配置最佳化、系統最佳化、快取機制和高併發處理策略,旨在幫助專業從業者深入理解並有效應用Nginx。

關注TechLead,復旦博士,分享雲服務領域全維度開發技術。擁有10+年網際網路服務架構、AI產品研發經驗、團隊管理經驗,復旦機器人智慧實驗室成員,國家級大學生賽事評審專家,發表多篇SCI核心期刊學術論文,阿里雲認證的資深架構師,上億營收AI產品研發負責人。

file

1. Nginx簡介與核心架構

file

1.1 Nginx簡介

Nginx (engine x) 是一個高效能的 HTTP 和反向代理伺服器,也是一個 IMAP/POP3/SMTP 郵件代理伺服器。由 Igor Sysoev 於2004年首次釋出,其設計目標是解決 C10K 問題,即在一臺伺服器上同時處理一萬個併發連線。Nginx 以其高併發處理能力、低資源消耗和模組化設計而聞名,廣泛應用於 Web 伺服器、反向代理、負載均衡等場景。

1.1.1 主要特性

  • 高併發處理能力:Nginx 使用非同步、非阻塞事件驅動架構,能夠高效地處理大量併發連線。
  • 低資源消耗:相對於傳統的程序或執行緒模型,Nginx 使用更少的記憶體和 CPU 資源。
  • 模組化設計:Nginx 的功能透過模組實現,使用者可以根據需求載入不同的模組。
  • 高可擴充套件性:透過第三方模組和 Lua 指令碼,Nginx 能夠輕鬆擴充套件其功能。
  • 豐富的功能:支援 HTTP/2、反向代理、負載均衡、快取、SSL/TLS、WebSocket 等。

1.2 核心架構

Nginx 的核心架構設計是其高效能和高可用性的關鍵。核心架構包括模組化設計、事件驅動模型、Master-Worker 程序模型和高效的請求處理流程。

1.2.1 模組化設計

Nginx 採用模組化設計,核心功能和擴充套件功能都透過模組實現。模組分為核心模組、標準 HTTP 模組和第三方模組。使用者可以根據需要啟用或禁用模組,靈活配置 Nginx 的功能。

  • 核心模組:實現 Nginx 的基本功能,如事件處理、記憶體管理、配置解析等。
  • 標準 HTTP 模組:提供 HTTP 服務的功能,如靜態檔案服務、反向代理、負載均衡等。
  • 第三方模組:由社群或開發者提供,擴充套件 Nginx 的功能,如 Lua 模組、Redis 模組等。
# 配置示例:啟用和配置 HTTP 模組
http {
    server {
        listen 80;
        server_name example.com;
        
        location / {
            root /var/www/html;
            index index.html index.htm;
        }
        
        location /proxy {
            proxy_pass http://backend_server;
        }
    }
}

1.2.2 事件驅動模型

Nginx 使用非同步、非阻塞事件驅動模型,能夠高效地處理併發連線。事件驅動模型基於 epoll(Linux)、kqueue(FreeBSD)等高效的 I/O 多路複用機制,實現事件的高效分發和處理。

  • 非同步非阻塞:所有 I/O 操作都透過事件通知機制完成,不會阻塞程序。
  • 高效的事件分發:透過 epoll、kqueue 等機制,Nginx 能夠快速分發和處理大量併發連線的事件。
// 示例:基於 epoll 的事件迴圈
for (;;) {
    int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
    for (int i = 0; i < n; i++) {
        if (events[i].events & EPOLLIN) {
            // 處理讀事件
        } else if (events[i].events & EPOLLOUT) {
            // 處理寫事件
        }
    }
}

1.2.3 Master-Worker 程序模型

Nginx 採用 Master-Worker 程序模型,確保高併發處理能力和高可靠性。Master 程序負責管理 Worker 程序,處理訊號和管理共享資源。Worker 程序處理實際的請求,互不干擾,提高了併發處理能力和穩定性。

  • Master 程序:啟動、停止 Worker 程序,處理訊號(如重新載入配置),管理共享資源(如快取)。
  • Worker 程序:處理客戶端請求,每個 Worker 程序獨立處理不同的連線,避免相互影響。
# 配置示例:設定 Worker 程序數量
worker_processes auto;

events {
    worker_connections 1024;
}

1.2.4 請求處理流程

Nginx 的請求處理流程高度最佳化,能夠高效地處理 HTTP 請求。主要流程包括接收請求、解析請求、選擇處理模組、生成響應和傳送響應。

  • 接收請求:透過事件驅動模型接收客戶端請求。
  • 解析請求:解析 HTTP 請求頭,生成請求上下文。
  • 選擇處理模組:根據配置選擇相應的模組處理請求,如靜態檔案服務、反向代理等。
  • 生成響應:呼叫處理模組生成響應資料。
  • 傳送響應:透過事件驅動模型傳送響應給客戶端。
# 配置示例:靜態檔案服務和反向代理
http {
    server {
        listen 80;
        server_name example.com;

        location / {
            root /var/www/html;
            index index.html index.htm;
        }

        location /proxy {
            proxy_pass http://backend_server;
        }
    }
}

2. Nginx反向代理與負載均衡

2.1 反向代理基礎

反向代理伺服器在客戶端和伺服器之間充當中介,接收客戶端的請求並將其轉發給後端伺服器,然後將後端伺服器的響應返回給客戶端。Nginx 作為反向代理伺服器的優勢在於其高併發處理能力、靈活的配置和豐富的功能。

2.1.1 反向代理的優勢

  • 隱藏後端伺服器:反向代理隱藏了後端伺服器的真實 IP 和埠,提升了安全性。
  • 負載均衡:反向代理可以將請求分發到多臺後端伺服器,實現負載均衡。
  • 快取:反向代理伺服器可以快取後端伺服器的響應,減少後端伺服器的壓力,提高響應速度。
  • SSL 終止:反向代理伺服器可以處理 SSL/TLS 加密,減輕後端伺服器的負擔。

2.1.2 反向代理配置示例

http {
    upstream backend {
        server backend1.example.com;
        server backend2.example.com;
    }

    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend;
            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;
        }
    }
}

2.2 負載均衡策略

Nginx 支援多種負載均衡策略,能夠根據不同的需求選擇合適的策略將請求分發到後端伺服器。

2.2.1 輪詢 (Round Robin)

輪詢是 Nginx 的預設負載均衡策略,將請求依次分發到每臺後端伺服器。該策略簡單高效,適用於後端伺服器效能均衡的情況。

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
}

2.2.2 最少連線 (Least Connections)

最少連線策略將請求分發到當前活動連線數最少的伺服器,適用於後端伺服器效能不均衡的情況。

upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
}

2.2.3 IP 雜湊 (IP Hash)

IP 雜湊策略根據客戶端 IP 計算雜湊值,將同一客戶端的請求分發到同一臺伺服器,適用於需要會話保持的場景。

upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
}

2.2.4 權重 (Weight)

權重策略為每臺伺服器設定權重,權重越高,伺服器接收到的請求越多,適用於後端伺服器效能不均衡且需要手動調整分配比例的情況。

upstream backend {
    server backend1.example.com weight=3;
    server backend2.example.com weight=1;
}

2.3 配置例項

下面提供幾個反向代理和負載均衡的實際配置示例,以幫助理解和應用這些概念。

2.3.1 基本反向代理配置

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend1.example.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;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

2.3.2 動靜分離配置

動靜分離是指將動態請求和靜態請求分別處理,以提高效率。Nginx 可以將靜態檔案請求直接由 Nginx 處理,而將動態請求轉發給後端伺服器。

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend1.example.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;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /static/ {
        root /var/www/html;
        expires 30d;
    }
}

2.3.3 負載均衡配置

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
        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;
    }
}

2.4 健康檢查

Nginx 還可以對後端伺服器進行健康檢查,確保請求不會分發到不可用的伺服器。透過配置 ngx_http_upstream_module 模組,可以實現簡單的健康檢查功能。

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    server backend3.example.com down;
}

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_pass http://backend;
    }
}

在此配置中,backend3.example.com 被標記為 down,Nginx 將不會將請求分發到這臺伺服器。更高階的健康檢查可以透過第三方模組如 ngx_http_upstream_check_module 實現。

2.5 高階反向代理配置

2.5.1 快取配置

Nginx 可以作為快取伺服器,透過快取後端伺服器的響應,減少後端伺服器的負擔,提升響應速度。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_cache my_cache;
        proxy_pass http://backend;
        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;
    }
}

2.5.2 SSL 終止

Nginx 可以處理 SSL/TLS 加密,解密客戶端請求後將其轉發給後端伺服器,減輕後端伺服器的加密負擔。

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;

    location / {
        proxy_pass http://backend;
        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;
    }
}

3. Nginx效能最佳化

Nginx 以其高效能和高併發處理能力著稱,但在實際應用中,合理的效能最佳化策略仍能顯著提升其效能。本文將詳細探討 Nginx 的效能最佳化方法,包括配置最佳化、系統最佳化、快取機制和高併發最佳化。

3.1 配置最佳化

Nginx 的配置對其效能有著至關重要的影響。合理的配置可以減少資源消耗,提高處理效率。

3.1.1 Worker 程序配置

Nginx 的 worker_processes 引數決定了處理請求的工作程序數量。一般建議將其設定為等於伺服器的 CPU 核心數,以充分利用多核 CPU 的並行處理能力。

worker_processes auto;

auto 表示自動檢測 CPU 核心數,並設定相應數量的工作程序。

3.1.2 Worker 連線數配置

worker_connections 引數決定了每個工作程序可以處理的最大連線數。為了提高併發處理能力,建議將其設定為儘可能大的值。

events {
    worker_connections 1024;
}

這個配置表示每個工作程序最多可以處理 1024 個併發連線。

3.1.3 快取配置

Nginx 提供多種快取機制,可以快取後端伺服器的響應,減少後端伺服器的壓力,提高響應速度。常用的快取機制包括 FastCGI 快取和代理快取。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

server {
    listen 80;
    server_name example.com;

    location / {
        proxy_cache my_cache;
        proxy_pass http://backend;
        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;
    }
}

這個配置建立了一個快取區域 my_cache,並在反向代理時啟用了快取。

3.2 系統最佳化

除了 Nginx 的配置最佳化,對作業系統的最佳化也能顯著提高 Nginx 的效能。

3.2.1 檔案描述符限制

Nginx 處理大量併發連線時,需要開啟大量的檔案描述符。預設的檔案描述符限制可能不足,需透過修改系統配置提高限制。

# 臨時修改
ulimit -n 65535

# 永久修改,編輯 /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535

3.2.2 TCP 連線最佳化

調整 TCP 連線引數,可以減少網路延遲,提高併發處理能力。

# 調整核心引數,編輯 /etc/sysctl.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30

# 應用配置
sysctl -p

3.3 快取機制

快取是提升 Nginx 效能的重要手段。透過快取機制,Nginx 可以將後端伺服器的響應儲存在本地,減少後端伺服器的負載。

3.3.1 FastCGI 快取

FastCGI 快取用於快取 FastCGI 應用程式的響應,例如 PHP。

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=fastcgi_cache:10m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";

server {
    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;

        fastcgi_cache fastcgi_cache;
        fastcgi_cache_valid 200 60m;
        fastcgi_cache_use_stale error timeout invalid_header updating;
    }
}

3.3.2 代理快取

代理快取用於快取反向代理的響應,減少後端伺服器的負載。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;

server {
    location / {
        proxy_cache my_cache;
        proxy_pass http://backend;
        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;
    }
}

3.4 高併發最佳化

Nginx 在處理高併發連線時,透過非同步非阻塞的事件驅動模型,能夠高效地處理大量併發連線。以下是一些針對高併發場景的最佳化策略。

3.4.1 啟用 keepalive

keepalive 可以保持客戶端和伺服器之間的連線,提高連線重用率,減少連線建立和釋放的開銷。

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    keepalive 32;
}

server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

3.4.2 調整緩衝區大小

調整 Nginx 的緩衝區大小,可以提高大檔案傳輸的效率,減少記憶體碎片。

http {
    server {
        client_body_buffer_size 16K;
        client_header_buffer_size 1k;
        large_client_header_buffers 4 16k;
        output_buffers 1 32k;
        postpone_output 1460;
    }
}

3.4.3 啟用 Gzip 壓縮

啟用 Gzip 壓縮,可以減少傳輸的資料量,提高響應速度。

http {
    gzip on;
    gzip_types text/plain application/xml;
    gzip_min_length 1000;
    gzip_comp_level 5;
}

如有幫助,請多關注
TeahLead KrisChang,10+年的網際網路和人工智慧從業經驗,10年+技術和業務團隊管理經驗,同濟軟體工程本科,復旦工程管理碩士,阿里雲認證雲服務資深架構師,上億營收AI產品業務負責人。

相關文章