Nginx效能優化及負載均衡
一、Nginx是什麼
Nginx是一款高效能的 HTTP 和反向代理伺服器,由俄羅斯人Igor Sysoev(伊戈爾·賽索耶夫)為俄羅斯網站Rambler.ru開發的,在Rambler.ru網站平穩的運行了四年,而且俄羅斯超過20%的虛擬主機平臺採用Nginx作為反向代理伺服器。
在國內,使用nginx網站有:百度、京東、金山愛詞霸、新浪、校內網、淘寶、YUPOO相簿、豆瓣、迅雷看看、網易、騰訊等。
二、Nginx的優點
- 高併發量:根據官方給出的資料,能夠支援高達 50,000 個併發連線數的響應;
- 記憶體消耗少:處理靜態檔案,同樣起 web 服務,比 apache 佔用更少的記憶體及資源,所有它是輕量級的;
- 簡單穩定:配置簡單,基本在一個conf檔案中配置,效能比較穩定,可以7*24小時長時間不間斷執行;
- 模組化程度高:Nginx是高度模組化的設計,編寫模組相對簡單,包括 gzipping, byte ranges, chunked responses,以及 SSI-filter 等 filter,支援 SSL 和 TLSSNI;
- 支援Rwrite重寫規則:能夠根據域名、URL的不同, 將HTTP請求分發到不同的後端伺服器群組;
- 支援多系統:Nginx程式碼完全用C語言從頭寫成,已經移植到許多體系結構和作業系統,包括:Linux、FreeBSD、Solaris、Mac OS X、AIX以及Microsoft Windows,由於Nginx是免費開源的,可以在各系統上編譯並使用;
三、Nginx的缺點
- 動態處理差:nginx處理靜態檔案好,耗費記憶體少,但是處理動態頁面則很雞肋,現在一般前端用nginx作為反向代理抗住壓力,Tomcat作為後端處理動態請求。
- rewrite弱:雖然nginx支援rewrite功能,但是相比於Apache來說,Apache比nginx 的rewrite 強大;
四、正向代理
正向代理類似一個跳板機,代理訪問外部資源。
舉個例子:
我是一個使用者,我訪問不了某網站,但是我能訪問一個代理伺服器,這個代理伺服器呢,他能訪問那個我不能訪問的網站,於是我先連上代理伺服器,告訴他我需要那個無法訪問網站的內容,代理伺服器去取回來,然後返回給我。從網站的角度,只在代理伺服器來取內容的時候有一次記錄,有時候並不知道是使用者的請求,也隱藏了使用者的資料,這取決於代理告不告訴網站。
客戶端必須設定正向代理伺服器,當然前提是要知道正向代理伺服器的IP地址,還有代理程式的埠。
總結來說:
正向代理是一個位於客戶端和原始伺服器(origin server)之間的伺服器,為了從原始伺服器取得內容,客戶端向代理髮送一個請求並指定目標(原始伺服器),然後代理向原始伺服器轉交請求並將獲得的內容返回給客戶端。客戶端必須要進行一些特別的設定才能使用正向代理。
正向代理的用途:
- 訪問原來無法訪問的資源,如google;
- 可以做快取,加速訪問資源;
- 對客戶端訪問授權,上網進行認證;
- 代理可以記錄使用者訪問記錄(上網行為管理),對外隱藏使用者資訊;
五、反向代理
對於反向代理來說,客戶端是無感知代理的存在的,反向代理對外都是透明的,訪問者者並不知道自己訪問的是一個代理。因為客戶端不需要任何配置就可以訪問。
反向代理(Reverse Proxy)實際執行方式是指以代理伺服器來接受internet上的連線請求,然後將請求轉發給內部網路上的伺服器,並將從伺服器上得到的結果返回給internet上請求連線的客戶端,此時代理伺服器對外就表現為一個伺服器。
反向代理的作用:
- 保證內網的安全,可以使用反向代理提供WAF功能,阻止web攻擊。大型網站,通常將反向代理作為公網訪問地址,Web伺服器是內網。
- 負載均衡,通過反向代理伺服器來優化網站的負載
二者的區別:
- 正向代理中,代理伺服器和客戶端處於同一網路環境下,對server透明;
- 反向代理中,代理伺服器和服務端處於同一網路環境下,對client透明;
- 實際上,代理伺服器在兩種代理中做的事都是收發請求和響應。正向代理代理客戶端傳送請求給服務端,反向代理代理服務端響應資料給客戶端;
六、負載均衡及反向代理配置
負載均衡
反向代理
七、效能優化
一般來說nginx配置檔案中對優化比較有作用的為以下幾項:
1、worker_processes 8
nginx程序數,建議按照cpu數目來指定,一般為它的倍數
2、worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000
為每個程序分配cpu,上例中將8個程序分配到8個cpu,當然可以寫多個,或者將一個程序分配到多個cpu
3、worker_rlimit_nofile 102400
這個指令是指當一個nginx程序開啟的最多檔案描述符數目,理論值應該是最多開啟檔案數(ulimit -n)與nginx程序數相除,但是nginx分配請求並不是那麼均勻,所以最好與ulimit -n的值保持一致
4、use epoll
使用epoll的I/O模型,用這個模型來高效處理非同步事件
5、worker_connections 102400
每個程序允許的最多連線數,理論上每臺nginx伺服器的最大連線數為:worker_processes*worker_connections
6、keepalive_timeout 60
http連線超時時間,預設是60s,功能是使客戶端到伺服器端的連線在設定的時間內持續有效,當出現對伺服器的後繼請求時,該功能避免了建立或者重新建立連線。切記這個引數也不能設定過大!否則會導致許多無效的http連線佔據著nginx的連線數,終nginx崩潰!
7、client_header_buffer_size 4k
客戶端請求頭部的緩衝區大小,這個可以根據你的系統分頁大小來設定,一般一個請求的頭部大小不會超過1k,不過由於一般系統分頁都要大於1k,所以這裡設定為分頁大小。分頁大小可以用命令getconf PAGESIZE取得
8、open_file_cache max=102400 inactive=20s
這個將為開啟檔案指定快取,預設是沒有啟用的,max指定快取數量,建議和開啟檔案數一致,inactive是指經過多長時間檔案沒被請求後刪除快取
9、open_file_cache_valid 30s
這個是指多長時間檢查一次快取的有效資訊
10、open_file_cache_min_uses 1
open_file_cache指令中的inactive引數時間內檔案的最少使用次數,如果超過這個數字,檔案描述符一直是在快取中開啟的,如上例,如果有一個檔案在inactive時間內一次沒被使用,它將被移除
11、server_tokens off
隱藏響應頭中的有關作業系統和web server(Nginx)版本號的資訊,這樣對於安全性是有好處的
下面是一個簡單的nginx配置檔案:
user www www; worker_processes 8; worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000; error_log /www/log/nginx_error.log crit; pid /usr/local/nginx/nginx.pid; worker_rlimit_nofile 204800; events { use epoll; worker_connections 204800; } http { include mime.types; default_type application/octet-stream; charset utf-8; server_names_hash_bucket_size 128; client_header_buffer_size 2k; large_client_header_buffers 4 4k; client_max_body_size 8m; sendfile on; tcp_nopush on; keepalive_timeout 60; fastcgi_cache_path /usr/local/nginx/fastcgi_cache levels=1:2 keys_zone=TEST:10m inactive=5m; fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 16k; fastcgi_buffers 16 16k; fastcgi_busy_buffers_size 16k; fastcgi_temp_file_write_size 16k; fastcgi_cache TEST; fastcgi_cache_valid 200 302 1h; fastcgi_cache_valid 301 1d; fastcgi_cache_valid any 1m; fastcgi_cache_min_uses 1; fastcgi_cache_use_stale error timeout invalid_header http_500; open_file_cache max=204800 inactive=20s; open_file_cache_min_uses 1; open_file_cache_valid 30s; tcp_nodelay on; gzip on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain application/x-javascript text/css application/xml; gzip_vary on; server { listen 8080; server_name backup.aiju.com; index index.php index.htm; root /www/html/; location /status { stub_status on; } location ~ .*\.(php|php5)?$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fcgi.conf; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$ { expires 30d; } log_format access '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" $http_x_forwarded_for'; access_log /www/log/access.log access; } }
關於核心引數的優化(在/etc/sysctl.conf檔案內):
1、net.ipv4.tcp_max_tw_buckets = 6000
timewait的數量,預設是180000。(Deven:因此如果想把timewait降下了就要把tcp_max_tw_buckets值減小)
2、net.ipv4.ip_local_port_range = 1024 65000
允許系統開啟的埠範圍
3、net.ipv4.tcp_tw_recycle = 0
啟用TIME-WAIT狀態sockets快速回收功能;用於快速減少在TIME-WAIT狀態TCP連線數。1表示啟用;0表示關閉。但是要特別留意的是:這個選項一般不推薦啟用,因為在NAT(Network Address Translation)網路下,會導致大量的TCP連線建立錯誤,從而引起網站訪問故障
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
實際上,net.ipv4.tcp_tw_recycle功能的開啟,要需要net.ipv4.tcp_timestamps(一般系統預設是開啟這個功能的)這個開關開啟後才有效果;
當tcp_tw_recycle 開啟時(tcp_timestamps 同時開啟,快速回收 socket 的效果達到),對於位於NAT裝置後面的 Client來說,是一場災難!
會導致到NAT裝置後面的Client連線Server不穩定(有的 Client 能連線 server,有的 Client 不能連線 server)。
也就是說,tcp_tw_recycle這個功能,是為內部網路(網路環境自己可控 ” ——不存在NAT 的情況)設計的,對於公網環境下,不宜使用。
通常來說,回收TIME_WAIT狀態的socket是因為“無法主動連線遠端”,因為無可用的埠,而不應該是要回收記憶體(沒有必要)。
即:需求是Client的需求,Server會有“埠不夠用”的問題嗎?
除非是前端機,需要大量的連線後端服務,也就是充當著Client的角色。
正確的解決這個總是辦法應該是:
net.ipv4.ip_local_port_range = 9000 6553 #預設值範圍較小
net.ipv4.tcp_max_tw_buckets = 10000 #預設值較小,還可適當調小
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4、net.ipv4.tcp_tw_reuse = 1
開啟重用功能,允許將TIME-WAIT狀態的sockets重新用於新的TCP連線。這個功能啟用是安全的,一般不要去改動!
5、net.ipv4.tcp_syncookies = 1
開啟SYN Cookies,當出現SYN等待佇列溢位時,啟用cookies來處理
6、net.core.somaxconn = 262144
Web應用中listen函式的backlog預設會給我們核心引數的net.core.somaxconn限制到128,而nginx定義的NGX_LISTEN_BACKLOG預設為511,所以有必要調整這個值
7、net.core.netdev_max_backlog = 262144
每個網路介面接收資料包的速率比核心處理這些包的速率快時,允許送到佇列的資料包的最大數目
8、net.ipv4.tcp_max_orphans = 262144
系統中最多有多少個TCP套接字不被關聯到任何一個使用者檔案控制代碼上。如果超過這個數字,孤兒連線將即刻被複位並打印出警告資訊。這個限制僅僅是為了防止簡單的DoS攻擊,不能過分依靠它或者人為地減小這個值,更應該增加這個值(如果增加了記憶體之後)
9、net.ipv4.tcp_max_syn_backlog = 262144
錄的那些尚未收到客戶端確認資訊的連線請求的最大值。對於有128M記憶體的系統而言,預設值是1024,小記憶體的系統則是128
10、net.ipv4.tcp_timestamps = 1
時間戳可以避免序列號的卷繞。一個1Gbps的鏈路肯定會遇到以前用過的序列號。時間戳能夠讓核心接受這種“異常”的資料包。這裡需要將其關掉。
11、net.ipv4.tcp_synack_retries = 1
為了開啟對端的連線,核心需要傳送一個SYN並附帶一個迴應前面一個SYN的ACK。也就是所謂三次握手中的第二次握手。這個設定決定了核心放棄連線之前傳送SYN+ACK包的數量
12、net.ipv4.tcp_syn_retries = 1
在核心放棄建立連線之前傳送SYN包的數量
13、net.ipv4.tcp_fin_timeout = 30
如果套接字由本端要求關閉,這個引數 決定了它保持在FIN-WAIT-2狀態的時間。對端可以出錯並永遠不關閉連線,甚至意外當機。預設值是60秒。2.2 核心的通常值是180秒,你可以按這個設定,但要記住的是,即使你的機器是一個輕載的WEB伺服器,也有因為大量的死套接字而記憶體溢位的風險,FIN- WAIT-2的危險性比FIN-WAIT-1要小,因為它最多隻能吃掉1.5K記憶體,但是它們的生存期長些
14、net.ipv4.tcp_keepalive_time = 30
當keepalive起用的時候,TCP傳送keepalive訊息的頻度。預設是2小時
下面貼出一個常用的核心引數的標準配置:
1 net.ipv4.ip_forward = 0 2 net.ipv4.conf.default.rp_filter = 1 3 net.ipv4.conf.default.accept_source_route = 0 4 kernel.sysrq = 0 5 kernel.core_uses_pid = 1 6 net.ipv4.tcp_syncookies = 1 7 kernel.msgmnb = 65536 8 kernel.msgmax = 65536 9 kernel.shmmax = 68719476736 10 kernel.shmall = 4294967296 11 net.ipv4.tcp_max_tw_buckets = 6000 12 net.ipv4.tcp_sack = 1 13 net.ipv4.tcp_window_scaling = 1 14 net.ipv4.tcp_rmem = 4096 87380 4194304 15 net.ipv4.tcp_wmem = 4096 16384 4194304 16 net.core.wmem_default = 8388608 17 net.core.rmem_default = 8388608 18 net.core.rmem_max = 16777216 19 net.core.wmem_max = 16777216 20 net.core.netdev_max_backlog = 262144 21 net.core.somaxconn = 262144 22 net.ipv4.tcp_max_orphans = 3276800 23 net.ipv4.tcp_max_syn_backlog = 262144 24 net.ipv4.tcp_timestamps = 0 25 net.ipv4.tcp_synack_retries = 1 26 net.ipv4.tcp_syn_retries = 1 27 net.ipv4.tcp_tw_recycle = 1 28 net.ipv4.tcp_tw_reuse = 1 29 net.ipv4.tcp_mem = 94500000 915000000 927000000 30 net.ipv4.tcp_fin_timeout = 1 31 net.ipv4.tcp_keepalive_time = 30 32 net.ipv4.ip_local_port_range = 1024 65000 33 net.ipv4.ip_conntrack_max = 6553500