進程間的關係
- Nginx 支持僅單進程(master)提供服務
- 常態的部署是使用一個 master 進程來管理多個 worker 進程
- Worker 數量與 CPU 核心數相等,進程切換代價最小
使用多進程的好處
- master 進程僅專注於純管理工作,為管理員提供命令行服務(啟動、停止、重配置、升級)
- master 進程需要比較大的權限,通常會以 root 使用者啟動
- 一個 worker 進程出錯後,其他 worker 仍然可以正常服務
- 充分利用 SMP(Symmetric multiprocessing) 多核架構,實現微觀上真正的多核併發處理
- Worker 通常不會進入睡眠狀態:可以同時處理多個請求,不像 Apache 每個進程只能同時處理一個請求,以致進程切換代價大
配置語法
每個模組都有自己感興趣的配置項,大部分模組都必須在 nginx.conf
中讀取到某個配置後才會啟用,例如只有當配置 http {…} 時, ngx_http_module
模組才會啟用,其他依賴的模組也才能正常使用
區塊配置項
1 2 3 4 5 6 7 8 9 10 11 |
http { ... gzip on; server { ... location /webstatic { gzip off; } } } |
- 由名稱及一對大括號組成,如
http
,server
,location
都屬於區塊配置項 - 傳入的參數取決於解析這個區塊配置項的模組
- 大括號表示包含其中的配置同時生效
- 可以嵌套,內層配置直接繼承外層
- 當內外層配置發生衝突,以哪層配置為準,取決於解析這個區塊配置項的模組,例如範例的
gzip
開關
配置項語法格式
1 2 |
名稱 參數1 參數2; |
- 名稱必須合法的(是某個 Nginx 模組想要處理的)
- 傳入的參數取決於解析這個區塊配置項的模組
- 若任一參數包含空格符,須要用單引號或雙引號包住
- 以分號結尾
通用計算單位
- 空間: K | k | M | m
- 時間: ms | s | m | h | d | w | M | y
前提是解析配置的模組使用了 Nginx 特定的解析方法,才能解析單位
使用變數
- 許多模組解析請求時都會提供多個變數,如
remote_addr
,request
- 使用要帶上 $ 前綴
- 在配置項使用這些變數,只有少數模組支援,並非通用的作法
基本配置
- 配置可以依照功能區分為四種:1) 用來調整進程,定位問題的相關配置 2) 運行相關配置 3)優化性能相關的配置 4) 事件相關的配置
- 有些配置項即使沒有明確配置,仍會套用默認值,如
daemon
用來調整進程,定位問題的相關配置
daemon
: 守護進程,脫離終端於背景運行的,避免進程被終端的訊號打斷;在 debug 及研究 Nginx 時設為 off 非常有用master_process
: 是否以多進程服務error_log
: 設定日誌,須注意磁碟空間是否能應付所選的 level (預設為 error)debug_connection
: 實屬事件類配置,參數為 IP 或 CIDR,只有請求來自於批配的地址,才會輸出日誌,在高併發請求下定位特定請求很有幫助
如果日誌級別設為 debug,需要在 ./configure 時加上 –with-debug
worker_rlimit_core
: 限制可儲存的核心傾印(coredumps)大小working_directory
:worker 進程的工作目錄,唯一的用途是用來指定 coredump 的目錄
運行相關配置
env
:用來直接設置系統的環境變數include
: 將其他配置文件引入當前的nginx.conf
,可以是絕對或相對路徑,即/usr/local/nginx/conf
pid
: master 進程 ID 的 pid 文件存放路徑user
: 定義 worker 進程以哪個 user 及 group 的身份運行worker_rlimit_nofile
: 定義一個 worker 能打開最大檔案描述符(file descriptor)數worker_rlimit_sigpending
: 限制單一客戶端發送的信號佇列大小
優化性能相關的配置
worker_process_number
: 定義 worker 數量
每個 worker 都是單執行緒,它會調用各個模組來實現不同功能。如果確認調用這些模組不會出現阻塞,則 worker 數量應該等於 CPU 核心數;如果調用會出現阻塞,應配置稍多一點 worker。例如,如果業務方面會導致使用者請求大量靜態文件,且伺服器內存較小,以致大部分請求都必須訪問磁碟,而不是內存中的磁碟緩存,那麼磁碟 I/O 的調用可能會造成 worker 阻塞
如果 worker 數量大於 CPU 核心數,多個 worker 都在搶同一個 CPU,會增加進程切換帶來的消耗(Linux 是搶佔式內核)
worker_cpu_affinity
將 worker 指定到 CPU 內核,僅在 Linux 有效(sched_setaffinity)
1 2 3 |
worker_process 4; worker_cpu_affinity 1000 0100 0010 0001; |
ssl_engine
: 如果伺服器上有 SSL 硬體加速設備,可以透過匹配裝置加快 SSL 處理速度,可以使用openssl engine -t
查看是否有加速設備timer_resolution
: 每次事件調用(epoll, select, pool, kqueue)響應時,都會執行一次 gettimeofday,用內核時鐘來更新 Nginx 的緩存時鐘;這對現今內核來說,只是一次虛擬系統呼叫(vsyscall,代價相對早期來說已經小很多,不太須要動到這個配置worker_priority
: 決定 worker 的 nice 優先權
當多個程序都處於可執行狀態時,本次內核執行哪個將按照各自的優先權決定,優先權越高,分配到的時間片段也越大(如最小 5ms 最大 800ms)。nice 值是靜態優先權,真正優先順序還內核還會參考執行情況做動態調整。nice 範圍是 -20(最高) ~ +19(最低),不建議設到比內核進程還優先(通常是 -5)
事件相關的配置
accpet_mutex
: 是否打開 Nginx 的負載均衡鎖,可以讓多個 worker 輪流且序列化地與新的客戶端建立 TCP 連接;當 worker 建立的連線數接近 worker_connections ,建立新連接的機會減低- lock_file: 當編譯程序或作業系統導致 Nginx 不支援原子鎖,會使用文件鎖來實現 accept 鎖
accept_mutex_delay
: 同一時間只有一個 worker 能取得 accept 鎖,當 worker 取不到,至少要等待多少時間才能再次取鎖- multi_accept:每當事件模型通知有新連接,盡可能對本次調度中客戶端發起的所有請求都建立連接
use
: 使用何種事件模型,Nginx 會自動選擇,性能最高的是 epollworker_connections
: 每個 worker 同時可以處理的最大連接數
靜態 Web 服務器基本配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
http { gzip on; upstream { ... } ... server { listen localhost:80; ... location /webstatic { if ... { ... } root /opt/webresource; } location ~* .(jpg|jpeg|png|gif)$ { ... } } } |
- 主要功能由
ngx_http_core_module
實現 - 配置可以依照功能區分為八種:1) 虛擬主機與分發請求 2) 文件路徑 3) 分配內存及磁碟 4) 網路連接 5) MIME 類型 6) 對請求的限制 7) 優化文件操作 8) 對請求的特殊處理
虛擬主機與分發請求相關的配置
server
: 每個 server 塊被視為一台虛擬主機,只處理相對應的主機域名請求(透過附屬的server_name
配置)listen
: 決定如何監聽端口defualt_server
: 當請求無法批配文件中所有主機域名,就會選用此默認的 server 區塊backlog
: 在建立 TCP 連接的三次握手過程中,會先將連接放置在 backlog;若已滿,往後的請求會建立失敗deferred
: 客戶建立完 TCP 連接,內核會等到客戶真的發送請求數據才調度 worker,以減輕 worker 負擔;適用於高併發ssl
: 在當前監聽的端口上建立的連接必須基於 ssl
server_name
: Nginx 取出請求頭部的 Host,與每個 server 進行匹配,決定哪個 server 處理該請求- 匹配的優先順序: 1) 完全匹配 2) 前通配符,如
*.example.com
3) 後通配符,如www.example.*
4) 正則表達式 - 若無法匹配,則遵循順序: 1) 選擇有指定 default_server 的 server 2) 選擇第一個 server
- 匹配的優先順序: 1) 完全匹配 2) 前通配符,如
server_names_hash_bucket_size
: 定義每個用來存放 server_name 的散列桶的大小,加快匹配速度server_names_hash_max_size
: 影響散列表發生衝突的機率,值越大,散列 key 的衝突減少,消耗的內存也越大server_name_in_redirect
: 在重定向請求時會使用 server_name 第一個主機名稱來取代請求頭部的 Hostlocation
: 根據請求的 URI 來決定哪個 location 處理該請求- 可以使用正則表達式
=
代表完全匹配;~
代表 case sensitive~*
代表 case insensitive^~
: 代表匹配前段 URI;@
代表服務內部請求的重定向,不直接處理請求- 有順序,第一個被匹配到的 location 優先處理
- 使用
/
作為參數,表示匹配所有請求,放在最後可用於「如果不匹配,則…」使用情境
文件路徑相關的配置
root
: 請求 URI 的根目錄,可以用在http
,server
,location
區塊alias
: 與root
的差別在於,location 的前段 URI 僅用於匹配,在磁碟映射會被棄用;因此也只能用在 location 區塊
1 2 3 4 |
location ~ /these/uri/will/be/discard { alias /usr/local/nginx/conf/; } |
當請求 /these/uri/will/be/discard/nignx.conf
則回傳 /usr/local/nginx/conf/nginx.conf
1 2 3 4 |
location ~ ^/test/(\w+)\.(\w+)$ { alias /usr/local/nginx/$2/$1.$2 } |
當請求 /test/nginx.conf
則回傳 /usr/local/nginx/conf/nginx.conf
index
: 通常 URI 是/
時表示訪問網站的首頁,可接多個參數,從最後一個參數開始向前匹配error_page
: 當某個請求返回錯誤碼,則參考此配置,重定向至新的 URI;也可在重定向後更改錯誤碼
1 2 |
error_page 404 =200 /empty.gif |
1 2 3 4 5 6 7 |
location / { error_page 404 @fallback } location @fallback { proxy_pass http://backend } |
try_files
: 照順序訪問每一個路徑參數,如果可以有效讀取,則返回;如果找不到,就重定向到最後一個 URI 參數
1 2 3 4 5 |
try_files /system/maintenance.html $uri $uri/index.html $uri.html @other location @other { proxy_pass http://backend } |
分配內存及磁碟相關的配置
client_body_in_file_only
: 請求 body 一律寫入磁碟client_body_in_single_buffer
: 請求 body 一律寫入內存 buffer,如果超出client_body_buffer_size
限制,則寫入磁碟cliebt_header_buffer_size
: 請求頭部寫入內存 buffer 的數量及大小,若超出則分配large_client_header_buffer_size
定義的大小,若再超出則返回 414- 請求中一般有多個頭部,單一個 header 不得超出單個 buffer 大小
- 請求頭部的總和不得超過 buffer 個數 * buffer 大小
client_body_temp_path
: 請求 body 超出 buffer 須寫入磁碟的臨時目錄,隨著文件數量會遞增子目錄,避免單一目錄文件數量過多導致性能下降connection_pool_size
: 每個建立成功的 TCP 連接會分配一個內存池,於連線關閉時回收;須謹慎設置,過大會使內存消耗大,過小會觸發更多次的內存分配,request_pool_size
: 每個請求都會分配一個內存池,用於減少內核對於小塊內存的分配次數,於請求結束時回收
網路連接相關的配置
client_header_timeout
: 接收頭部時若超過一定時間沒有讀取到資料,則返回 408;client_body_timeout
則定義讀取 body 的超時send_timeout
: 響應時若客戶端超過一定時間沒有接收,則關閉連接reset_timeout_connection
: 超時後項客戶端發送 RST 包來重置連接,非使用正常情形的四次握手關閉,減少 FINWAIT1, FINWAIT2, TIME_WAIT 狀態的連接;使用上會造成一些問題,通常不會開啟lingering_close
: 關閉連接前是否處理客戶端發送的數據lingering_time
: 對於上傳大文件很有幫助;當用戶請求的 Content-Length 大於max_client_body_size
,會返回 413,但客戶端可能不管此返回仍繼續上傳,而超過此設置時間 Nginx 將會強制關閉連接keepalive_disable
: keepalive 功能讓多個請求復用一個 HTTP 長連接,可提高服務性能,但有些瀏覽器如 IE6, Safari 在 keepalive 的 POST 有功能性問題,針對這些瀏覽器默認停用 keepalivekeepalive_timeout
: 閒置超過一定時間,伺服器關閉連接,照規範這個時間會傳給瀏覽器,瀏覽器如何對待 keepalive(例如也去關閉連接)則視各家瀏覽器而不同keepalive_requests
: 一個長連接允許發送的最大請求數tcp_nodelay
: 對 keepalive 連接是啟用 TCP_NODELAYtcp_nopush
: 在sendfile
開啟的狀況下,是否啟用 TCP_CORK
MIME 類型相關的配置
types
: 設定文件副檔名對應到哪種 MIME typedefault_type
: 自types
匹配不到時套用的預設值types_hash_bucket_size
: 意義同server_names_hash_bucket_size
types_hash_max_size
: 意義同server_names_hash_max_size
限制請求的配置
limit_expect
: 限制請求方法
1 2 3 4 5 |
limit_expect GET { allow 192.168.1.0/32; deny all; } |
client_max_body_size
: 瀏覽器發送的請求含較大的 body 時,頭部附有 Content-Length 字段,Nginx 不用接收完所有 body,若 Content-Length 超出即回傳 413limit_rate
: 對請求限速,限制每秒可傳輸多少 bytes,可針對不同客戶端做不同設定limit_rate_after
: 當 Nginx 響應速度超過多少微秒才開始限速
優化文件操作的配置
sendfile
: 啟用 Linux 的 sendfile 系統調用來發送文件,減少了內核態與用戶態之間的兩次內存複製,從磁碟讀取文件後直接在內核態發送到網卡,提高效率aio
: 是否啟用 Linux 的異步文件 I/O,與sendfile
功能是互斥的directio
: 是否啟用 Linux 的 O_DIRECT,通常能優化對大文件的讀取directio_alignment
: 以 directio 讀取文件時的對齊方式open_file_cache
: 在內存儲存三種資訊 1) 文件指標、大小、修改時間 2) 訪問過得目錄結構 3) 遺失的或權限不足的文件資訊;透過 max 參數以 LRU 限制緩存數量;透過 inactive 刪除久未使用的緩存open_file_cache_errors
: 是否緩存打開文件時出現的錯誤訊息open_file_cache_min_uses
: 與open_file_cache
的 inactive 搭配使用,若在指定的時段訪問次數不到最小值,則刪除該緩存open_file_cache_valid
: 多久檢查一次緩存是否有效
對請求特殊處理的配置
ignore_invalid_headers
: 當請求頭部不合法,回傳 400underscores_in_headers
: 是否禁止在請求頭使用 _if_modified_since
: 決定如何處理請求頭的 If-Modified-Since 資訊;瀏覽器會在本地緩存文件,並紀錄取得的時間,下次向伺服器請求時會帶上此資訊,而伺服器會判斷是否回傳新的文件(若有修改)或 304 Not Modifiedlog_not_found
: 是否紀錄找不到請求文件的錯誤merge_slashes
: 是否合併 URI 中鄰近的 /resolver_address
: 設置 DNS 的 IP 位址resolver_timeout
: DNS 解析的超時時間server_tokens
: 是否在錯誤的響應頭部註明版本資訊
反向代理服務器基本配置
- 反向代理必須能夠處理大量併發,,將Internet 上的連接請求轉發給內部網路中的上游伺服器
- 當客戶端發出請求,Nginx 並不會立刻轉發,而是緩存完才向上游伺服器發起連接
- 先緩存請求的缺點是延長了請求處理的時間,優點是降低了上游伺服器的併發壓力
1 2 3 4 5 6 7 8 9 10 11 12 |
upstream backend { server backend1.example.com weight=5; server 127.0.0.1:8080 max_fails=3 fail_timeout=30s; server unix:/tmp/backend3; } server { location / { proxy_pass http://backend; } } |
負載均衡的配置
upstream
: 定義上游服務器的集群,便於在proxy_pass
使用server
: 上游服務器的名字weight
: 轉發的優先權重fail_timeout
,max_fails
: 在時段內轉發失敗幾次就認定該伺服器暫時為不可用
ip_hash
:根據客戶端 IP 計算出 key ,並根據集群數量做 mod,來決定總是轉發至哪台伺服器- 與
weight
不得同時使用 - 如果集群有某台伺服器不可用,不該直接刪除配置,而是打上
down
標記,避免破壞原本雜湊的一致性
- 與
反向代理的配置
proxy_pass
: 可以是上游伺服器的 URL,或事先定義的 upstream 區塊名稱proxy_set_header
: 轉發 Host 頭部(默認情況下不轉發)proxy_method
: 更改轉發時的請求方法proxy_hide_header
: 響應時,指定哪些 HTTP 頭部字段不轉發,默認為 Date, Server, X-Pad, X-Accel-*proxy_pass_header
: 與proxy_hide_header
作用相反,指定哪些 http 頭部字段可以轉發proxy_pass_request_body
: 是否對上游伺服器發送 HTTP bodyproxy_pass_request_headers
: 是否對上游伺服器發送 HTTP 頭部proxy_redirect
: 當上游伺服器響應重定向(301)或刷新(302),重設 HTTP 頭部 的 location 或 refresh 字段proxy_next_upstream
: 轉發請求若出現錯誤,繼續換一台上游伺服器處理
文章豐富, 感謝.
小錯誤: try_fiels 應是 try_files.
謝謝你的指正,已修正錯誤了