高性能Web服務器Nginx及相關新技術的應用實踐
什麼是Nginx?
• Nginx (「engine x」) 是俄羅斯人Igor Sysoev(塞索耶夫)編寫的一款高性能的 HTTP 和反向代理服務器。
• Nginx 已經在俄羅斯最大的門戶網站── Rambler Media(
www.rambler.ru
)上運行了4年時間,同時俄羅斯超過20%的虛擬主機平臺採用Nginx做爲反向代理服務器。
• 在國內,已經有新浪播客、搜狐通行證、網易新聞、網易博客、金山逍遙網、金山愛詞霸、校內網、YUPOO相冊、豆瓣、迅雷看看等多家網站、頻道使用 Nginx 服務器
Nginx的優勢①
• 一、高併發鏈接:官方測試可以支撐5萬併發鏈接,在實際生產環境中跑到2~3萬併發鏈接數。
• 二、內存消耗少:在3萬併發鏈接下,開啓的10個Nginx 進程才消耗150M內存(15M*10=150M)。
• 三、配置文件很是簡單:風格跟程序同樣通俗易懂。
• 四、成本低廉:Nginx爲開源軟件,能夠無償使用。而購買F5 BIG-IP、NetScaler等硬件負載均衡交換機則須要十多萬至幾十萬人民幣。
Nginx的優勢②
• 五、支持Rewrite重寫規則:可以根據域名、URL的不一樣,將 HTTP 請求分到不一樣的後端服務器羣組。
• 六、內置的健康檢查功能:若是 Nginx Proxy 後端的某臺 Web 服務器宕機了,不會影響前端訪問。
• 七、節省帶寬:支持 GZIP 壓縮,能夠添加瀏覽器本地緩存的 Header 頭。
• 八、穩定性高:用於反向代理,宕機的機率微乎其微。
單臺Nginx支撐了高達2.8萬的活動併發鏈接數
Nginx的主要應用類別
• 一、使用 Nginx 結合FastCGI運行 PHP、JSP 、Perl等程序
• 二、使用 Nginx 做反向代理、負載均衡、規則過濾
• 三、使用 Nginx 運行靜態HTML頁、圖片
• 四、Nginx與其餘新技術的結合應用
Nginx在金山逍遙網中的應用案例
金山逍遙網(xoyo.com)是金山遊戲官方網站,爲金山軟件旗下的各款遊戲提供新聞資訊、客戶服務、在線充值、視聽互動、在線活動、博客、相冊、論壇、玩家社區等內容建設和在線服務支持。
金山逍遙網
Nginx七層負載均衡的應用
Nginx承擔每一個機房Web負載均衡服務
簡單的Nginx負載均衡配置①
……
upstream bbs_server_pool {
server 192.168.1.15:80 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.16:80 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.17:80 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.18:80 weight=1 max_fails=2 fail_timeout=30s;
}
……
在nginx.conf配置文件中,用upstream指令定義一組反向代理/負載均衡後端服務器池。
……
server{
listen 80;
server_name bbs.yourdomain.com *.bbs.yourdomain.com;
location /
{
proxy_pass http://bbs_server_pool;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
access_log off;
}
……
• proxy_pass http://bbs_server_pool; 用於指定反向代理的服務器池。
• proxy_set_header Host $host; 當後端Web服務器上也配置有多個虛擬主機時,須要用該Header來區分反向代理哪一個主機名。
• proxy_set_header X-Forwarded-For $remote_addr; 若是後端Web服務器上的程序須要獲取用戶IP,請從該Header頭獲取
Nginx負載均衡的雙機熱備
一般狀況下的負載均衡HA高可用
優勢:實現了雙機熱備、故障自動轉移。
缺點:備機服務器處於閒置狀態,浪費了硬件資源。
逍遙網Nginx負載均衡雙機互備
正常狀況下,兩臺Nginx負載均衡服務器所有處於活動狀態,對外提供服務。
服務器①綁定IP別名
• /sbin/ifconfig eth0:ha1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
• /sbin/route add -host 61.1.1.2 dev eth0:ha1
• /sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
• 在服務器①的外網網卡eth0上,綁定了一個虛擬IP 61.1.1.2,綁定完成後發送arping包給網關。
服務器②綁定IP別名
• /sbin/ifconfig eth0:ha2 61.1.1.3 broadcast 61.1.1.255 netmask 255.255.255.0 up
• /sbin/route add -host 61.1.1.3 dev eth0:ha2
• /sbin/arping -I eth0 -c 3 -s 61.1.1.3 61.1.1.1
• 在服務器②的外網網卡eth0上,綁定了一個虛擬IP 61.1.1.3,綁定完成後發送arping包給網關。
新的Nginx雙機互備(發生故障時)
自動接管公網虛擬IP,實現故障轉移
服務器①去除IP別名
• /sbin/ifconfig eth0:ha1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 down
• 經過兩臺服務器之間的互相檢測機制,當服務器①上的檢測程序發現自身的Nginx沒法訪問時,中止綁定虛擬IP 61.1.1.2
服務器②接管原服務器①的虛擬IP
• /sbin/ifconfig eth0:ha1 61.1.1.2 broadcast 61.1.1.255 netmask 255.255.255.0 up
• /sbin/route add -host 61.1.1.2 dev eth0:ha1
• /sbin/arping -I eth0 -c 3 -s 61.1.1.2 61.1.1.1
• 給網關發送Arping包,保證了網關上IP、MAC地址對應關係可以立刻更改,可以作到強行接管虛擬IP。
Nginx負載均衡URL分發
硬件、軟件七層負載均衡對比:NetScaler與Nginx
根據不一樣的URL轉發到不一樣服務器
server{
listen 80;
server_name abc.domain.com;
location ~ ^/admincp.php
{
proxy_pass http://192.168.1.11;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
location /
{
proxy_pass http://php_server_pool;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
Web相關文件的實時自動同步
少許文件的多服務器自動同步
• 使用Linux 2.6內核的inotify監控Linux文件系統事件。
• 利用開源的lsync監聽某一目錄,若是目錄內文件發生增、刪、改,利用Rsync協議自動同步到多臺服務器。
http://code.google.com/p/lsyncd/
• lsyncd /data0/htdocs/hu.xoyo.com/data/ 192.168.5.1::hu_data/ 192.168.5.2::hu_data/ 192.168.5.3::hu_data/
大量文件的多服務器自動同步
• 使用Linux 2.6內核的inotify監控Linux文件系統事件。
• 修改可監控的最大目錄數量
echo 50000000 > /proc/sys/fs/inotify/max_user_watches
• 金山逍遙網開發的sersync文件自動同步程序,適合大量文件的自動同步,並能夠在文件同步完成後,自動調用CDN緩存刷新接口,刷新發生修改、刪除的文件的訪問URL。
Nginx的Web緩存服務
Nginx的緩存功能
• Nginx從0.7.48版本開始,支持了相似Squid的緩存功能;
• 緩存把URL及相關組合看成Key,用md5編碼哈希後保存;
• Nginx的Web緩存服務只能爲指定URL或狀態碼設置過時時間,不支持相似Squid的PURGE指令,手動清除指定緩存頁面;
• 採用MMAP實現,設置的緩存區大小不能超過物理內存+SWAP的值。
反向代理中的Nginx.conf緩存配置①
……
#設置Web緩存區名稱爲cache_one,緩存空間大小爲2000MB,1天清理一次緩存,單個文件超過5m不緩存。
proxy_cache_path /data0/proxy_cache_path levels=1:2 keys_zone=cache_one:2000m inactive=1d max_size=5m;
#注:proxy_temp_path和proxy_cache_path指定的路徑必須在同一分區
proxy_temp_path /data0/proxy_temp_path;
upstream my_server_pool {
server 192.168.1.2:80 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.3:80 weight=1 max_fails=2 fail_timeout=30s;
}
……
server
{
listen 80;
server_name my.domain.com;
location /
{
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://my_server_pool;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|js|css)$
{
#對圖片、JS、CSS進行緩存,使用Web緩存區cache_one
proxy_cache cache_one;
#對不一樣HTTP狀態碼緩存設置不一樣的緩存時間
proxy_cache_valid 200 10m;
proxy_cache_valid 304 3m;
proxy_cache_valid 301 302 1h;
proxy_cache_valid any 1m;
#設置Web緩存的Key值,Nginx根據Key值md5哈希存儲緩存,這裏根據「域名、URI、客戶端請求Header頭中的If-Modified-Since信息」組合成Key。
proxy_cache_key $host$request_uri$http_if_modified_since;
#反向代理,訪問後端內容源服務器
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_pass http://my_server_pool;
}
access_log off;
}
Nginx緩存功能的優勢
• 對於修改實時性要求不高的圖片、Flash、CSS樣式文件、JavaScript文件,能夠在Nginx反向代理(負載均衡)服務器上設置緩存,不用每次請求都轉發到後端Web服務器,加快了響應速度。
• 減小了Nginx與後端Web服務器的鏈接數,提升了Nginx處理性能。
Nginx的Rewrite重寫規則
Nginx Rewrite規則相關指令
Nginx Rewrite規則相關指令有if、rewrite、set、return、break等,其中rewrite是最關鍵的指令。一個簡單的Nginx Rewrite規則語法以下:
rewrite ^/b/(.*)\.html /play.php?video=$1 break;
若是加上if語句,示例以下:
if (!-f $request_filename)
{
rewrite ^/img/(.*)$ /site/$host/images/$1 last;
}
Nginx與Apache的Rewrite規則實例對比①
簡單的Nginx和Apache 重寫規則區別不大,基本上可以徹底兼容。例如:
Apache Rewrite 規則:
RewriteRule ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 [L]
RewriteRule ^/ceshi/$ /zl/ceshi.php [L]
RewriteRule ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 [L]
RewriteRule ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 [L]
Nginx Rewrite 規則:
rewrite ^/(mianshi|xianjing)/$ /zl/index.php?name=$1 last;
rewrite ^/ceshi/$ /zl/ceshi.php last;
rewrite ^/(mianshi)_([a-zA-Z]+)/$ /zl/index.php?name=$1_$2 last;
rewrite ^/pingce([0-9]*)/$ /zl/pingce.php?id=$1 last;
由以上示例能夠看出,Apache的Rewrite規則改成Nginx的Rewrite規則,其實很簡單:Apache的RewriteRule指令換成Nginx的rewrite指令,Apache的[L]標記換成Nginx的last標記,中間的內容不變。
若是Apache的Rewrite規則改成Nginx的Rewrite規則後,使用nginx -t命令檢查發現nginx.conf配置文件有語法錯誤,那麼能夠嘗試給條件加上引號。例如一下的Nginx Rewrite規則會報語法錯誤:
rewrite ^/([0-9]{5}).html$ /x.jsp?id=$1 last;
加上引號就正確了:
rewrite "^/([0-9]{5}).html$" /x.jsp?id=$1 last;
Apache與Nginx的Rewrite規則在URL跳轉時有細微的區別:
Apache Rewrite 規則:
RewriteRule ^/html/tagindex/([a-zA-Z]+)/.*$ /$1/ [R=301,L]
Nginx Rewrite 規則:
rewrite ^/html/tagindex/([a-zA-Z]+)/.*$ http://$host/$1/ permanent;
以上示例中,咱們注意到,Nginx Rewrite 規則的置換串中增長了「http://$host」,這是在Nginx中要求的。
另外,Apache與Nginx的Rewrite規則在變量名稱方面也有區別,例如:
Apache Rewrite 規則:
RewriteRule ^/user/login/$ /user/login.php?login=1&forward=http://%{HTTP_HOST} [L]
Nginx Rewrite 規則:
rewrite ^/user/login/$ /user/login.php?login=1&forward=http://$host last;
Apache與Nginx Rewrite 規則的一些功能相同或相似的指令、標記對應關係:
Apache的RewriteCond指令對應Nginx的if指令;
Apache的RewriteRule指令對應Nginx的rewrite指令;
Apache的[R]標記對應Nginx的redirect標記;
Apache的[P]標記對應Nginx的last標記;
Apache的[R,L]標記對應Nginx的redirect標記;
Apache的[P,L]標記對應Nginx的last標記;
Apache的[PT,L]標記對應Nginx的last標記;
Nginx與Apache的多條件Rewrite示例①
容許指定的域名訪問本站,其餘域名一概跳轉到http://www.aaa.com
Apache Rewrite 規則:
RewriteCond %{HTTP_HOST} ^(.*?)\.domain\.com$
RewriteCond %{HTTP_HOST} !^qita\.domain\.com$
RewriteCond %{DOCUMENT_ROOT}/market/%1/index.htm -f
RewriteRule ^/wu/$ /market/%1/index.htm [L]
Nginx的if指令不支持嵌套,也不支持AND、OR等多條件匹配,相比於Apache的RewriteCond,顯得麻煩一些,可是,咱們能夠經過下一頁的Nginx配置寫法來實現這個示例:
Nginx Rewrite 規則:
if ($host ~* ^(.*?)\.domain\.com$)
{
set $var_wupin_city $1;
set $var_wupin '1';
}
if ($host ~* ^qita\.domain\.com$)
{
set $var_wupin '0';
}
if (!-f $document_root/market/$var_wupin_city/index.htm)
{
set $var_wupin '0';
}
if ($var_wupin ~ '1')
{
rewrite ^/wu/$ /market/$var_wupin_city/index.htm last;
}php