日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
為高負載網(wǎng)絡(luò)優(yōu)化Nginx和Node.js

在搭建高吞吐量web應(yīng)用這個議題上,NginX和Node.js可謂是天生一對。他們都是基于事件驅(qū)動模型而設(shè)計,可以輕易突破Apache等傳統(tǒng)web服務(wù)器的C10K瓶頸。預(yù)設(shè)的配置已經(jīng)可以獲得很高的并發(fā),不過,要是大家想在廉價硬件上做到每秒數(shù)千以上的請求,還是有一些工作要做的。

這篇文章假定讀者們使用NginX的HttpProxyModule來為上游的node.js服務(wù)器充當(dāng)反向代理。我們將介紹Ubuntu 10.04以上系統(tǒng)sysctl的調(diào)優(yōu),以及node.js應(yīng)用與NginX的調(diào)優(yōu)。當(dāng)然,如果大家用的是Debian系統(tǒng),也能達到同樣的目標(biāo),只不過調(diào)優(yōu)的方法有所不同而已。

網(wǎng)絡(luò)調(diào)優(yōu)

如果不先對Nginx和Node.js的底層傳輸機制有所了解,并進行針對性優(yōu)化,可能對兩者再細致的調(diào)優(yōu)也會徒勞無功。一般情況下,Nginx通過TCP socket來連接客戶端與上游應(yīng)用。

我們的系統(tǒng)對TCP有許多門限值與限制,通過內(nèi)核參數(shù)來設(shè)定。這些參數(shù)的默認值往往是為一般的用途而定的,并不能滿足web服務(wù)器所需的高流量、短生命的要求。

這里列出了調(diào)優(yōu)TCP可供候選的一些參數(shù)。為使它們生效,可以將它們放在/etc/sysctl.conf文件里,或者放入一個新配置文件,比如/etc/sysctl.d/99-tuning.conf,然后運行sysctl -p,讓內(nèi)核裝載它們。我們是用sysctl-cookbook來干這個體力活。

需要注意的是,這里列出來的值是可以安全使用的,但還是建議大家研究一下每個參數(shù)的含義,以便根據(jù)自己的負荷、硬件和使用情況選擇一個更加合適的值。

 
 
 
 
  1. net.ipv4.ip_local_port_range='1024 65000'
  2. net.ipv4.tcp_tw_reuse='1'
  3. net.ipv4.tcp_fin_timeout='15'
  4. net.core.netdev_max_backlog='4096'
  5. net.core.rmem_max='16777216'
  6. net.core.somaxconn='4096'
  7. net.core.wmem_max='16777216'
  8. net.ipv4.tcp_max_syn_backlog='20480'
  9. net.ipv4.tcp_max_tw_buckets='400000'
  10. net.ipv4.tcp_no_metrics_save='1'
  11. net.ipv4.tcp_rmem='4096 87380 16777216'
  12. net.ipv4.tcp_syn_retries='2'
  13. net.ipv4.tcp_synack_retries='2'
  14. net.ipv4.tcp_wmem='4096 65536 16777216'
  15. vm.min_free_kbytes='65536'

重點說明其中幾個重要的。

net.ipv4.ip_local_port_range

為了替上游的應(yīng)用服務(wù)下游的客戶端,NginX必須打開兩條TCP連接,一條連接客戶端,一條連接應(yīng)用。在服務(wù)器收到很多連接時,系統(tǒng)的可用端口將很快被耗盡。通過修改net.ipv4.ip_local_port_range參數(shù),可以將可用端口的范圍改大。如果在/var/log/syslog中發(fā)現(xiàn)有這樣的錯誤: “possible SYN flooding on port 80. Sending cookies”,即表明系統(tǒng)找不到可用端口。增大net.ipv4.ip_local_port_range參數(shù)可以減少這個錯誤。

net.ipv4.tcp_tw_reuse

當(dāng)服務(wù)器需要在大量TCP連接之間切換時,會產(chǎn)生大量處于TIME_WAIT狀態(tài)的連接。TIME_WAIT意味著連接本身是關(guān)閉的,但資源還沒有釋放。將net_ipv4_tcp_tw_reuse設(shè)置為1是讓內(nèi)核在安全時盡量回收連接,這比重新建立新連接要便宜得多。

net.ipv4.tcp_fin_timeout

這是處于TIME_WAIT狀態(tài)的連接在回收前必須等待的最小時間。改小它可以加快回收。

如何檢查連接狀態(tài)

使用netstat:

netstat -tan | awk '{print $6}' | sort | uniq -c

或使用ss:

ss -s

NginX

 
 
 
 
  1. ss -s
  2. Total: 388 (kernel 541)
  3. TCP:   47461 (estab 311, closed 47135, orphaned 4, synrecv 0, timewait 47135/0), ports 33938
  4. Transport Total     IP        IPv6
  5. *          541       -         -        
  6. RAW        0         0         0        
  7. UDP        13        10        3        
  8. TCP        326       325       1        
  9. INET       339       335       4        
  10. FRAG       0         0         0

隨著web服務(wù)器的負載逐漸升高,我們就會開始遭遇NginX的某些奇怪限制。連接被丟棄,內(nèi)核不停報SYN flood。而這時,平均負荷和CPU使用率都很小,服務(wù)器明明是可以處理更多連接的狀態(tài),真令人沮喪。

經(jīng)過調(diào)查,發(fā)現(xiàn)有非常多處于TIME_WAIT狀態(tài)的連接。這是其中一個服務(wù)器的輸出:

有47135個TIME_WAIT連接!而且,從ss可以看出,它們都是已經(jīng)關(guān)閉的連接。這說明,服務(wù)器已經(jīng)消耗了絕大部分可用端口,同時也暗示我們,服務(wù)器是為每個連接都分配了新端口。調(diào)優(yōu)網(wǎng)絡(luò)對這個問題有一點幫助,但是端口仍然不夠用。

經(jīng)過繼續(xù)研究,我找到了一個關(guān)于上行連接keepalive指令的文檔,它寫道:

 設(shè)置通往上游服務(wù)器的最大空閑?;钸B接數(shù),這些連接會被保留在工作進程的緩存中。

有趣。理論上,這個設(shè)置是通過在緩存的連接上傳遞請求來盡可能減少連接的浪費。文檔中還提到,我們應(yīng)該把proxy_http_version設(shè)為"1.1",并清除"Connection"頭部。經(jīng)過進一步的研究,我發(fā)現(xiàn)這是一種很好的想法,因為HTTP/1.1相比HTTP1.0,大大優(yōu)化了TCP連接的使用率,而Nginx默認用的是HTTP/1.0。

按文檔的建議修改后,我們的上行配置文件變成這樣:

 
 
 
 
  1. upstream backend_nodejs {
  2.   server nodejs-3:5016 max_fails=0 fail_timeout=10s;
  3.   server nodejs-4:5016 max_fails=0 fail_timeout=10s;
  4.   server nodejs-5:5016 max_fails=0 fail_timeout=10s;
  5.   server nodejs-6:5016 max_fails=0 fail_timeout=10s;
  6.   keepalive 512;
  7. }

我還按它的建議修改了server一節(jié)的proxy設(shè)置。同時,加了一個 p roxy_next_upstream來跳過故障的服務(wù)器,調(diào)整了客戶端的 keepalive_timeout,并關(guān)閉訪問日志。配置變成這樣:

 
 
 
 
  1. server {
  2.   listen 80;
  3.   server_name fast.gosquared.com;
  4.   client_max_body_size 16M;
  5.   keepalive_timeout 10;
  6.   location / {
  7.     proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
  8.     proxy_set_header   Connection "";
  9.     proxy_http_version 1.1;
  10.     proxy_pass http://backend_nodejs;
  11.   }
  12.   access_log off;
  13.   error_log /dev/null crit;
  14. }

采用新的配置后,我發(fā)現(xiàn)服務(wù)器們占用的socket降低了90%。現(xiàn)在可以用少得多的連接來傳輸請求了。新的輸出如下:

 
 
 
 
  1. ss -s
  2. Total: 558 (kernel 604)
  3. TCP:   4675 (estab 485, closed 4183, orphaned 0, synrecv 0, timewait 4183/0), ports 2768
  4. Transport Total     IP        IPv6
  5. *          604       -         -        
  6. RAW        0         0         0        
  7. UDP        13        10        3        
  8. TCP        492       491       1        
  9. INET       505       501       4

Node.js

得益于事件驅(qū)動式設(shè)計可以異步處理I/O,Node.js開箱即可處理大量的連接和請求。雖然有其它一些調(diào)優(yōu)手段,但這篇文章將主要關(guān)注node.js的進程方面。

Node是單線程的,不會自動使用多核。也就是說,應(yīng)用不能自動獲得服務(wù)器的全部能力。

實現(xiàn)Node進程的集群化

我們可以修改應(yīng)用,讓它fork多個線程,在同一個端口上接收數(shù)據(jù),從而實現(xiàn)負載的跨越多核。Node有一個cluster模塊,提供了實現(xiàn)這個目標(biāo)所必需的所有工具,但要將它們加入應(yīng)用中還需要很多體力活。如果你用的是express,eBay有一個叫cluster2的模塊可以用。

防止上下文切換

當(dāng)運行多個進程時,應(yīng)該確保每個CPU核同一時間只忙于一個進程。一般來說,如果CPU有N個核,我們應(yīng)該生成N-1個應(yīng)用進程。這樣可以確保每個進程都能得到合理的時間片,而剩下的一個核留給內(nèi)核調(diào)度程序運行其它任務(wù)。我們還要確保服務(wù)器上基本不執(zhí)行除Node.js外的其它任務(wù),防止出現(xiàn)CPU的爭用。

我們曾經(jīng)犯過一個錯誤,在服務(wù)器上部署了兩個node.js應(yīng)用,然后每個應(yīng)用都開了N-1個進程。結(jié)果,它們互相之間搶奪CPU,導(dǎo)致系統(tǒng)的負荷急升。雖然我們的服務(wù)器都是8核的機器,但仍然可以明顯地感覺到由上下文切換引起的性能開銷。上下文切換是指CPU為了執(zhí)行其它任務(wù)而掛起當(dāng)前任務(wù)的現(xiàn)象。在切換時,內(nèi)核必須掛起當(dāng)前進程的所有狀態(tài),然后裝載和執(zhí)行另一個進程。為了解決這個問題,我們減少了每個應(yīng)用開啟的進程數(shù),讓它們公平地分享CPU,結(jié)果系統(tǒng)負荷就降了下來:

請注意上圖,看系統(tǒng)負荷(藍線)是如何降到CPU核數(shù)(紅線)以下的。在其它服務(wù)器上,我們也看到了同樣的情況。既然總的工作量保持不變,那么上圖中的性能改善只能歸功于上下文切換的減少。


新聞標(biāo)題:為高負載網(wǎng)絡(luò)優(yōu)化Nginx和Node.js
文章分享:http://www.5511xx.com/article/cojjeod.html