優化 Nginx worker 程序數
Nginx 有 master 和 worker 兩種程序,master 程序用于管理 worker 程序,worker 程序用于 Nginx 服務。
worker 程序數預設為 1 。
worker_processes 1;
worker 程序數應該設定為伺服器 CPU 的核數。
root@localhost ~# grep -c processor /proc/cpuinfo # 檢視CPU核數
2
root@localhost ~# vim /usr/local/nginx/conf/nginx.conf # 設定worker程序數
worker_processes 2;
worker_processes 這個參數最好是設定成 auto 自動比對程序數。
綁定 Nginx 程序到不同的 CPU 上
預設情況下,Nginx 的多個程序有可能跑在某一個 CPU 或 CPU 的某一核上,導緻 Nginx 程序使用硬體的資源不均,是以綁定 Nginx 程序到不同的 CPU 上是為了充分利用硬體的多 CPU 多核資源。
root@localhost ~# grep -c processor /proc/cpuinfo # 檢視CPU核數
2
worker_processes 2; # 2核CPU的配置
worker_cpu_affinity 01 10;
worker_processes 4; # 4核CPU的配置
worker_cpu_affinity 0001 0010 0100 1000;
worker_processes 8; # 8核CPU的配置
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 1000000;
優化 Nginx 單個程序允許的最大連接配接數
控制 Nginx 單個程序允許的最大連接配接數的參數為 worker_connections ,這個參數要根據伺服器性能和記憶體使用量來調整。
程序的最大連接配接數受 Linux 系統程序打開的最大檔案數的限制,隻有執行了 “ulimit -HSn 65535” 之後,worker_connections 才能生效。
連接配接數包括代理伺服器的連接配接、用戶端的連接配接等,Nginx 總并發連接配接數 = worker_processes * worker_connections。總數保持在 3w 左右即可。
worker_processes 2;
worker_cpu_affinity 01 10;
user nginx nginx;
events {
use epoll;
複制
worker_connections 15000;
複制
}
優化 Nginx worker 程序打開的最大檔案數
worker_rlimit_nofile 65535; # worker 程序打開的最大檔案數,可設定為優化後的 ulimit -HSn 的結果
開啟高效檔案傳輸模式
sendfile 參數用于開啟檔案的高效傳輸模式,該參數實際上是激活了 sendfile () 功能。
sendfile () 是作用于兩個檔案描述符之間的資料拷貝函數,這個拷貝操作是在核心之中的,被稱為 “零拷貝” 。sendfile 比 read 和 write 函數要高效得多,因為 read 和 write 函數要把資料拷貝到應用層再進行操作。
tcp_nopush 參數用于激活 Linux 上的 TCP_CORK socket 選項,此選項僅僅當開啟 sendfile 時才生效,tcp_nopush 參數可以把 http response header 和檔案的開始部分放在一個檔案裡釋出,以減少網絡封包段的數量。
http {
include mime.types;
default_type application/octet-stream;
sendfile on; # 開啟檔案的高效傳輸模式
tcp_nopush on; # 激活 TCP_CORK socket 選擇
tcp_nodelay on; # 資料在傳輸的過程中不進緩存
keepalive_timeout 65;
include vhosts/*.conf;
}
優化 Nginx 連接配接的逾時時間
連接配接逾時的作用
将無用的連接配接設定為盡快逾時,可以保護伺服器的系統資源(CPU、記憶體、磁盤)
當連接配接很多時,及時斷掉那些建立好的但又長時間不做事的連接配接,以減少其占用的伺服器資源
如果黑客攻擊,會不斷地和伺服器建立連接配接,是以設定連接配接逾時以防止大量消耗伺服器的資源
如果使用者請求了動态服務,則 Nginx 就會建立連接配接,請求 FastCGI 服務以及後端 MySQL 服務,設定連接配接逾時,使得在使用者容忍的時間内傳回資料
連接配接逾時存在的問題
伺服器建立新連接配接是要消耗資源的,是以,連接配接逾時時間不宜設定得太短,否則會造成并發很大,導緻伺服器瞬間無法響應使用者的請求。
有些 PHP 站點會希望設定成短連接配接,因為 PHP 程式建立連接配接消耗的資源和時間相對要少些。
有些 Java 站點會希望設定成長連接配接,因為 Java 程式建立連接配接消耗的資源和時間要多一些,這是由語言的運作機制決定的。
設定逾時時間
keepalive_timeout:用于設定用戶端連接配接保持會話的逾時時間,超過這個時間伺服器會關閉該連接配接。
client_header_timeout:用于設定讀取用戶端請求頭資料的逾時時間,如果逾時用戶端還沒有發送完整的 header 資料,伺服器将傳回 “Request time out (408)” 錯誤。
client_body_timeout:用于設定讀取用戶端請求主體資料的逾時時間,如果逾時用戶端還沒有發送完整的主體資料,伺服器将傳回 “Request time out (408)” 錯誤。
send_timeout:用于指定響應用戶端的逾時時間,如果超過這個時間,用戶端沒有任何活動,Nginx 将會關閉連接配接。
tcp_nodelay:預設情況下當資料發送時,核心并不會馬上發送,可能會等待更多的位元組組成一個資料包,這樣可以提高 I/O 性能,但是,在每次隻發送很少位元組的業務場景中,使用 tcp_nodelay 功能,等待時間會比較長。
http {
include mime.types;
複制
server_names_hash_bucket_size 512;
複制
default_type application/octet-stream;
複制
sendfile on;
複制
tcp_nodelay on;
複制
keepalive_timeout 65;
複制
client_header_timeout 15;
複制
client_body_timeout 15;
複制
send_timeout 25;
複制
include vhosts/*.conf;
複制
}
限制上傳檔案的大小
client_max_body_size 用于設定最大的允許用戶端請求主體的大小。
在請求頭中有 “Content-Length” ,如果超過了此配置項,用戶端會收到 413 錯誤,即請求的條目過大。
http {
client_max_body_size 8m; # 設定用戶端最大的請求主體大小為 8 M
複制
}
FastCGI 相關參數調優
當 LNMP 組合工作時,使用者通過浏覽器輸入域名請求 Nginx Web 服務:
如果請求的是靜态資源,則由 Nginx 解析後直接傳回給使用者;
如果是動态請求(如 PHP),那麼 Nginx 就會把它通過 FastCGI 接口發送給 PHP 引擎服務(即 php-fpm)進行解析,如果這個動态請求要讀取資料庫資料,那麼 PHP 就會繼續請求 MySQL 資料庫,以讀取需要的資料,并最終通過 Nginx 服務把擷取的資料傳回給使用者。
這就是 LNMP 環境的基本請求流程。
在 Linux 中,FastCGI 接口即為 socket ,這個 socket 可以是檔案 socket,也可以是 IP socket。
http {
include mime.types;
複制
default_type application/octet-stream;
複制
sendfile on;
複制
keepalive_timeout 65;
複制
fastcgi_connect_timeout 240; # Nginx伺服器和後端FastCGI伺服器連接配接的逾時時間
複制
fastcgi_send_timeout 240; # Nginx允許FastCGI伺服器傳回資料的逾時時間,即在規定時間内後端伺服器必須傳完所有的資料,否則Nginx将斷開這個連接配接
複制
fastcgi_read_timeout 240; # Nginx從FastCGI伺服器讀取響應資訊的逾時時間,表示連接配接建立成功後,Nginx等待後端伺服器的響應時間
複制
fastcgi_buffer_size 64k; # Nginx FastCGI 的緩沖區大小,用來讀取從FastCGI伺服器端收到的第一部分響應資訊的緩沖區大小
複制
fastcgi_buffers 4 64k; # 設定用來讀取從FastCGI伺服器端收到的響應資訊的緩沖區大小和緩沖區數量
複制
fastcgi_busy_buffers_size 128k; # 用于設定系統很忙時可以使用的 proxy_buffers 大小
複制
fastcgi_temp_file_write_size 128k; # FastCGI 臨時檔案的大小
複制
fastcti_temp_path /data/ngx_fcgi_tmp; # FastCGI 臨時檔案的存放路徑
fastcgi_cache_path /data/ngx_fcgi_cache levels=2:2 keys_zone=ngx_fcgi_cache:512m inactive=1d max_size=40g; # 緩存目錄
複制
server {
複制
listen 80;
複制
server_name www.abc.com;
複制
location / {
複制
root html/www;
複制
index index.html index.htm;
複制
}
複制
location ~ .*\.(php|php5)?$ {
複制
root html/www;
複制
fastcgi_pass 127.0.0.1:9000;
複制
fastcgi_index index.php;
複制
include fastcgi.conf;
複制
fastcgi_cache ngx_fcgi_cache; # 緩存FastCGI生成的内容,比如PHP生成的動态内容
複制
fastcgi_cache_valid 200 302 1h; # 指定http狀态碼的緩存時間,這裡表示将200和302緩存1小時
複制
fastcgi_cache_valid 301 1d; # 指定http狀态碼的緩存時間,這裡表示将301緩存1天
複制
fastcgi_cache_valid any 1m; # 指定http狀态碼的緩存時間,這裡表示将其他狀态碼緩存1分鐘
複制
fastcgi_cache_min_uses 1; # 設定請求幾次之後響應被緩存,1表示一次即被緩存
複制
fastcgi_cache_use_stale error timeout invalid_header http_500; # 定義在哪些情況下使用過期緩存
複制
fastcgi_cache_key http://$host$request_uri; # 定義 fastcgi_cache 的 key
複制
}
複制
}
複制
}
gzip 壓縮
Nginx gzip 壓縮子產品提供了壓縮檔案内容的功能,使用者請求的内容在發送到用戶端之前,Nginx 伺服器會根據一些具體的政策實施壓縮,以節約網站出口帶寬,同時加快資料傳輸效率,來提升使用者通路體驗。
需要壓縮的對象有 html 、js 、css 、xml 、shtml ,圖檔和視訊盡量不要壓縮,因為這些檔案大多都是已經壓縮過的,如果再壓縮可能反而變大。
另外,壓縮的對象必須大于 1KB,由于壓縮算法的特殊原因,極小的檔案壓縮後可能反而變大。
http {
gzip on; # 開啟壓縮功能
複制
gzip_min_length 1k; # 允許壓縮的對象的最小位元組
複制
gzip_buffers 4 32k; # 壓縮緩沖區大小,表示申請4個機關為32k的記憶體作為壓縮結果的緩存
複制
gzip_http_version 1.1; # 壓縮版本,用于設定識别HTTP協定版本
複制
gzip_comp_level 9; # 壓縮級别,1級壓縮比最小但處理速度最快,9級壓縮比最高但處理速度最慢
複制
gzip_types text/plain application/x-javascript text/css application/xml; # 允許壓縮的媒體類型
複制
gzip_vary on; # 該選項可以讓前端的緩存伺服器緩存經過gzip壓縮的頁面,例如用代理伺服器緩存經過Nginx壓縮的資料
複制
}
配置 expires 緩存期限
Nginx expires 的功能就是給使用者通路的靜态内容設定一個過期時間。
當使用者第一次通路這些内容時,會把這些内容存儲在使用者浏覽器本地,這樣使用者第二次及以後繼續通路該網站時,浏覽器會檢查加載已經緩存在使用者浏覽器本地的内容,就不會去伺服器下載下傳了,直到緩存的内容過期或被清除。
不希望被緩存的内容:廣告圖檔、網站流量統計工具、更新很頻繁的檔案。
緩存期限參考:新浪緩存 15 天,京東緩存 25 年,淘寶緩存 10 年。
server {
listen 80;
複制
server_name www.abc.com abc.com;
複制
root html/www;
複制
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ # 緩存的對象
複制
{
複制
expires 3650d; # 緩存期限為 10 年
複制
}
複制
}
配置防盜鍊
什麼是防盜鍊?
簡單地說,就是其它網站未經許可,通過在其自身網站程式裡非法調用其他網站的資源,然後在自己的網站上顯示這些調用的資源,使得被盜鍊的那一端消耗帶寬資源 。
通過 HTTP referer 實作防盜鍊。
#第一種,比對字尾
location ~ .*.(gif|jpg|jpeg|png|bm|swf|flv|rar|zip|gz|bz2)$ { # 指定需要使用防盜鍊的媒體資源
access_log off; # 不記錄日志
複制
expires 15d; # 設定緩存時間
複制
valid_referers none blocked .test.com .abc.com; # 表示僅允許這些域名通路上面的媒體資源
if ($invalid_referer) { # 如果域名不是上面指定的位址就傳回403
複制
return 403
複制
}
複制
}
#第二種,綁定目錄
location /images {
root /web/www/img;
複制
vaild_referers none blocked *.spdir.com *.spdir.top;
複制
if ($invalid_referer) {
複制
return 403;
複制
}
複制
}
server 代碼塊
server 代碼塊位于 http 代碼塊内部,每一個 server 都可以用來配置一個虛拟主機。也就是說,每一個 server 代表了一個虛拟伺服器的配置資訊。
可以添加多個 server 來配置多個虛拟主機。
server {
listen 80;
複制
server_name localhost;
複制
#access_log logs/host.access.log main;
複制
root "D:/phpStudy/WWW";
複制
location / {
複制
index index.html index.htm index.php l.php;
複制
autoindex off;
複制
}
複制
#error_page 404 /404.html;
複制
# redirect server error pages to the static page /50x.html
複制
#
複制
error_page 500 502 503 504 /50x.html;
複制
location = /50x.html {
複制
root html;
複制
}
複制
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
複制
#
複制
#location ~ \.php$ {
複制
# proxy_pass http://127.0.0.1;
複制
#}
複制
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
複制
#
複制
location ~ \.php(.*)$ {
複制
fastcgi_pass 127.0.0.1:9000;
複制
fastcgi_index index.php;
複制
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
複制
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
複制
fastcgi_param PATH_INFO $fastcgi_path_info;
複制
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
複制
include fastcgi_params;
複制
}
複制
# deny access to .htaccess files, if Apache's document root
複制
# concurs with nginx's one
複制
#
複制
#location ~ /\.ht {
複制
# deny all;
複制
#}
複制
}
server 中的主要配置有:
listen 虛拟主機監聽的端口
server_name 虛拟主機的域名或 IP 位址,可以配置多個(用空格隔開)
root 虛拟主機的根目錄
index 虛拟主機的首頁,也可以用 location 代碼塊來配置
access_log 虛拟主機的通路日志
error_log 虛拟主機的錯誤日志
error_page 錯誤頁面
location 代碼塊
location 代碼塊位于 server 代碼塊内部。
location 用于配置虛拟主機的 URI,它是一個非常重要的配置。
可以給每一個 server(虛拟主機)配置多個 location。
可以根據不同的 URI 配置不同的 location,來處理不同的請求。
location 的文法格式
location = | ~ | ~* | ^~ | @ uri {...}
其中, = | ~ | ~* | ^~ | @ 表示字首,也叫修飾符,是可選的;uri 表示普通字元串或正規表達式,是必須的。
@ 這個修飾符非常特殊,後面跟一個普通字元串,用于定義特殊的類型,被定義的類型隻能被 nginx 内部調用,用于内部的重定向。這個重定向純碎是 nginx 内部的一個轉發行為。
= 字元串完整比對。
~ 區分大小寫的正則比對。
~* 不區分大小寫的正則比對。
^~ 字元串字首比對,隻要比對到了,就不會再比對其他的正則 location。
如果沒有任何修飾符,也表示字元串字首比對,即字元串 location。
如果 location 中使用了修飾符~或者~*,那麼,這個 location 就是正則 location;否則,就是字元串 location。
多個 location 的比對順序
多個 location 的比對順序與 location 的位置順序沒有直接關系,比對順序為:
= 修飾符的優先級最高,表示完整比對。如果比對成功,則停止比對其他 location。
字元串 location 的優先級第二;多個字元串 location 的比對順序為從長到短,也就是說優先選擇長度最長的字元串比對;比對成功的字元串 location 如果使用了修飾符 ^~ 或者正好是精準比對,則不會再去檢驗正則 location。
正則 location 的優先級低于字元串 location;多個 正則 location 會按照配置檔案裡的位置順序進行比對,如果比對成功,就停止比對。
注意: 雖然字元串 location 的優先級高于正則 location。但是,如果比對成功的字元串 location 中沒有使用修飾符 ^~ ,也不是精準比對,那麼還會繼續檢測是否有比對的正則 location。如果比對到了正則 location,就立即使用該正則 location 并停止比對;否則,才會使用字元串 location。
也就是說,比對到的字元串 location 可能會被正則 location 所覆寫。
比對成功的字元串 location,如果不想再繼續檢測比對正則 location,有三種實作方式:
使用 = 修飾符,來進行完整比對。
使用 ^~ 修飾符,仍然還是字首比對。
如果字元串比對正好是精準的字首比對,也不會再去檢測正則 location。這是一種隐式的實作方式。
比對模式及其順序
location = /string 字元串完整比對,優先級最高。
location ^~ /string 字元串字首比對(不檢測正則 location)。
location ~ pattern 正則比對(區分大小寫)。
location ~* pattern 正則比對(不區分大小寫)。
location /string 不帶修飾符的字元串字首比對。
location / 預設比對,如果一個請求沒有比對到其他的 location,就會比對預設比對。它相當于 switch 中的 default 。
說明:對于字元串 location,如果沒有 = 修飾符,就都是字首比對;而正則 location,可能是字首比對、字尾比對、中間比對和完整比對中的任意一種,這取決于正規表達式本身。
配置預設首頁
location / {
index index.html index.htm index.php l.php;
複制
autoindex off;
複制
}
配置反向代理
location / {
proxy_pass http://localhost:8888;
複制
proxy_set_header Host $host;
複制
proxy_set_header X-Real-IP $remote_addr;
複制
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
複制
}
URL 美化(省略 index.php 入口檔案)
location / {
try_files $uri $uri/ /index.php?$query_string;
複制
}
upstream 代碼塊
upstream 代碼塊位于 http 代碼塊内部。
upstream 用于對伺服器叢集進行負載均衡的配置。
upstream name {
ip_hash;
複制
server 192.168.1.100:8000;
複制
server 192.168.1.100:8001 down;
複制
server 192.168.1.100:8002 max_fails=3;
複制
server 192.168.1.100:8003 fail_timeout=20s;
複制
server 192.168.1.100:8004 max_fails=3 fail_timeout=20s;
複制
}
ip_hash:手動指定排程算法。
down:表示該主機暫停服務。
max_fails:表示失敗最大次數,超過失敗最大次數就會暫停服務。
fail_timeout:表示如果請求受理失敗,暫停指定的時間之後重新發起請求。
配置檔案中的全局變量
$args #這個變量等于請求行中的參數。
$content_length #請求頭中的 Content-length 字段。
$content_type #請求頭中的 Content-Type 字段。
$document_root #目前請求在 root 指令中指定的值。
$host #請求主機頭字段,否則為伺服器名稱。
$http_user_agent #用戶端 agent 資訊
$http_cookie #用戶端 cookie 資訊
$limit_rate #這個變量可以限制連接配接速率。
$request_body_file #用戶端請求主體資訊的臨時檔案名。
$request_method #用戶端請求的動作,通常為 GET 或 POST。
$remote_addr #用戶端的 IP 位址。
$remote_port #用戶端的端口。
$remote_user #已經經過 Auth Basic Module 驗證的使用者名。
$request_filename #目前請求的檔案路徑,由 root 或 alias 指令與 URI 請求生成。
$query_string #與 $args 相同。
$scheme #HTTP 方法(如 http,https)。
$server_protocol #請求使用的協定,通常是 HTTP/1.0 或 HTTP/1.1。
$server_addr #伺服器位址,在完成一次系統調用後可以确定這個值。
$server_name #伺服器名稱。
$server_port #請求到達伺服器的端口号。
$request_uri #包含請求參數的原始 URI,不包含主機名,如:”/foo/bar.php?arg=baz”。
$uri #不帶請求參數的目前 URI,$uri 不包含主機名,如”/foo/bar.html”。
$document_uri #與 $uri 相同。
源碼附件已經打包好上傳到百度雲了,大家自行下載下傳即可~
連結: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27
提取碼: yu27
百度雲連結不穩定,随時可能會失效,大家抓緊儲存哈。
如果百度雲連結失效了的話,請留言告訴我,我看到後會及時更新~
開源位址
碼雲位址:
http://github.crmeb.net/u/defu
Github 位址:
http://github.crmeb.net/u/defu