1. 程式人生 > 其它 >Nginx效能優化及負載均衡

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