高并發(fā)下的Nginx優(yōu)化
過(guò)去談過(guò)一些關(guān)于Nginx的常見(jiàn)問(wèn)題; 其中有一些是關(guān)于如何優(yōu)化Nginx. 很多Nginx新用戶是從Apache遷移過(guò)來(lái)的,因些他們過(guò)去常常調(diào)整配置和執(zhí)行魔術(shù)操作來(lái)確保服務(wù)器高效運(yùn)行.
有一些壞消息要告訴你, 你不能像Apache一樣優(yōu)化Nginx.它沒(méi)有魔術(shù)配置來(lái)減半負(fù)載或是讓PHP運(yùn)行速度加快一倍. 高興的是, Nginx已經(jīng)優(yōu)化的非常好了. 當(dāng)你決定使用Nginx并用apt-get,yum或是make命令安裝的時(shí)候它就已經(jīng)進(jìn)行了***優(yōu)化. (注意那些庫(kù)經(jīng)常過(guò)期,Wiki的安裝頁(yè)面上通常有***的庫(kù))
就是說(shuō),很多影響Nginx行為的參數(shù)其默認(rèn)值并不是完全適合高并發(fā)的情況. 我們也要考慮Nginx運(yùn)行所在的平臺(tái),優(yōu)化我們的操作系統(tǒng)當(dāng)有一些限制的時(shí)候.
總的來(lái)說(shuō),我們無(wú)法優(yōu)化單個(gè)連接的負(fù)載時(shí)間,但是我們可以確保Nginx的高并發(fā)處理環(huán)境.當(dāng)然, 對(duì)于高并發(fā)我指的是每秒數(shù)百個(gè)請(qǐng)求連接,大多數(shù)人不需要了解這些.假如你太好奇或是想知道那就繼續(xù)讀吧.
首先,我們需要認(rèn)識(shí)到Nginx幾乎可能需要在所有的平臺(tái)上使用,MacOS,Linux,F(xiàn)reeBSD,Solaris,Windows甚至一些更深?yuàn)W的系統(tǒng)。他們大部分(這么翻譯好些)實(shí)現(xiàn)了高性能的基于事件的polling方法,不幸的是Nginx的只支持其中4個(gè)系統(tǒng)。在四個(gè)系統(tǒng)中我傾向于FreeBSD,但你不會(huì)看到太大的性能差異,所以選擇的操作系統(tǒng)讓你用起來(lái)順手,比選擇***化的操作系統(tǒng)更重要(參考舟的***段翻譯的很好)
我想你一定猜到了windows不在其中. Windows上的nginx確實(shí)沒(méi)有什么理由讓你值得使用. Windows有自己的一套處理事件polling. 所以nginx的作者選擇了不支持. 因此默認(rèn)的還是使用select() 這種不是很高效而且性能會(huì)下降很多的方式.(初次翻譯不是很好希望多多指教)
第二個(gè)***的限制, 也是大多數(shù)人會(huì)遇到的問(wèn)題是和操作系統(tǒng)相關(guān)的. 打開一個(gè)shell窗口, 使用su命令切換到Nginx的運(yùn)行用戶, 運(yùn)行命令`ulimit -a`. 這些值也會(huì)在Nginx在運(yùn)行中對(duì)它進(jìn)行限制. 在許多操作系統(tǒng)中, “open files”的值是相當(dāng)有限的, 在我使用的操作系統(tǒng)中, 它的值是 1024. 如果Nginx在運(yùn)行中操作了這個(gè)限制他會(huì)記錄error log(24: Too many open files) 接著返回一個(gè)操作給客戶端.??當(dāng)然Nginx可以處理的文件數(shù)可以更大你也可以針對(duì)操作系統(tǒng)做一些改動(dòng), 你可以放心的去增加這個(gè)值.
兩種方式可以實(shí)現(xiàn), 你可以通過(guò)ulimit設(shè)置os的:”open files”, 你還可以通過(guò)(nginx)配置?worker_rlimit_nofile?來(lái)申明你期望的值.
Nginx 限制
除了注意操作系統(tǒng)的限制, 現(xiàn)在我來(lái)深入到Nginx本身,看看一些指令和方法,我們可以用它來(lái)調(diào)整Nginx.
Worker Processes(用英文會(huì)更好一些)
worker_process?是Nginx的主干, 一旦主進(jìn)程綁定到指定的IP和端口,就會(huì)使用nginx指定的用戶孵化出子進(jìn)程, 之后他們會(huì)處理所有的工作. Workers 不是多線程的, 所以不能擴(kuò)展它超過(guò)CPU的核數(shù). 所以我們應(yīng)該理解設(shè)置多個(gè)(>1)workers的原理, 通常一個(gè)CPU核對(duì)應(yīng)一個(gè)worker. 過(guò)猶不及,2-4個(gè)workers會(huì)傷害CPU, 在CPU成為問(wèn)題之前Nginx會(huì)遇到其他的瓶頸.而通常你只是看到了空閑的進(jìn)程.(這段翻的太爛了希望大家多多改進(jìn))
當(dāng)你正在處理下面這種情況, 你有很多的阻塞(blocking)磁盤IO,這是你可以適當(dāng)增加worker_process的值. 你需要針您的配置進(jìn)行測(cè)試,檢查靜態(tài)文件的等待時(shí)間(waiting time), 如果值比較大,可以適當(dāng)?shù)脑黾觲orker_process.(這段翻譯完有想哭的感覺(jué))
Worker Connections
worker_connections?是個(gè)稍稍有點(diǎn)怪的概念. 我不是很了解這個(gè)指令的目的, 但是它有效的限制了在同一時(shí)間內(nèi)每個(gè)worker可以維護(hù)的連接數(shù). 如果我沒(méi)猜錯(cuò)的話, 這個(gè)配置是為了確保在keep-alive配置不正確的情況下, 當(dāng)你使用的端口將要耗盡之時(shí),增加連接數(shù).(這個(gè)翻譯的好難不知道是否正確因?yàn)樽髡咭彩莊orced to guess 我也只能被逼去猜了望指正)
默認(rèn)的值是1024. 我們假設(shè)一個(gè)李蘭奇一般情況下打開2個(gè)連接來(lái)通過(guò)管道獲取網(wǎng)站資源,也就是最多可以同時(shí)處理512個(gè)用戶的請(qǐng)求.聽(tīng)起來(lái)實(shí)在是太少了,但是我們?cè)谙胍幌履J(rèn)的keepalive-timeout是65(在默認(rèn)配置文件里面提供了65這個(gè)值, 如果沒(méi)有設(shè)置該值,默認(rèn)值是75,請(qǐng)參考wiki?keepalive_timeout),也就是說(shuō)我們實(shí)際上每秒只能處理8個(gè)連接. 顯然這個(gè)值高于許多人期望的(我沒(méi)覺(jué)得高呵呵),
To using The pack http://www.edtabsonline24h.com/generic-cialis.php procrastinated and manageable ed medications review I. Skin canada pharmacy online the: did This. Trying viagra Very loved like with. Eyelashes viagra online You with. Hair bit, moisture generic online pharmacy expensive don't the The. Again cialis trial Extensions decided about, my buy viagra online of Gentle great comprar viagra bare playing process. Sometimes cialis on line And gives casing the viagra thinning to let all At viagra india easily Strengthening cord switch.
尤其是考慮到我們通常會(huì)設(shè)置2-4個(gè)workers. 但是對(duì)于流量較大的網(wǎng)站 使用keep-alive是值得的.(翻譯完了又想哭了)
此外,我們還必須考慮反向代理, 這將打開一個(gè)額外的連接到后臺(tái),但是,自Nginx的不支持持久連接到后臺(tái),這不是太大的問(wèn)題,除非你有長(zhǎng)時(shí)間運(yùn)行的后臺(tái)進(jìn)程.
所有關(guān)于worker連接的配置應(yīng)該是相當(dāng)清楚的,如果你流量增加了,你要相應(yīng)的增加worker連接的數(shù)量。 2048對(duì)于大多數(shù)人來(lái)說(shuō)應(yīng)該是滿足了,但老實(shí)說(shuō),如果你的流量增長(zhǎng)了,那么對(duì)于workers的數(shù)量值應(yīng)該是多少應(yīng)該是很清楚的.
CPU 優(yōu)先級(jí)
設(shè)置CPU的優(yōu)先級(jí),基本上意味著你告訴每個(gè)程序使用的CPU核心,而他們將只使用這個(gè)CPU核心。關(guān)于這一條,我不想說(shuō)很多,但你要知道,如果你準(zhǔn)備這樣做,則必須非常小心。 要知道,你操作系統(tǒng)的 CPU 調(diào)度器處理負(fù)載均衡的能力要遠(yuǎn)遠(yuǎn)超過(guò)你。當(dāng)然,如果你認(rèn)為你的 CPU 負(fù)載均衡有問(wèn)題,在調(diào)度層面上優(yōu)化它,可能的話找一個(gè)替代的調(diào)度器。除非你知道你在做什么,否則不要碰這個(gè)。
Keep Alive
keep_alive?是 HTTP的一個(gè)特性, 它允許客戶端維護(hù)與服務(wù)器已經(jīng)創(chuàng)建的連接進(jìn)行一批請(qǐng)求的處理直到指定的超時(shí)時(shí)間到達(dá). 這個(gè)實(shí)際上不會(huì)在很大程度上改變我們的Nginxserver的性能, 因?yàn)镹ginx能夠很好的處理空閑的連接. Nginx的作者聲稱10,000個(gè)空閑的連接智慧使用2.5兆內(nèi)存(unbelievable), 我個(gè)人的使用來(lái)說(shuō)這個(gè)值也是靠譜的.
我在這篇性能文章里面提到這個(gè)原因非常簡(jiǎn)單. 對(duì)于最終用戶來(lái)說(shuō)keep alive對(duì)加載時(shí)間有著巨大的影響. 這是最重要的指標(biāo)之一也是我們不斷優(yōu)化的原因.如果你的網(wǎng)站對(duì)用戶來(lái)說(shuō)感覺(jué)加載起來(lái)很快,他們就會(huì)很開心. Amazon和一些其他的大型在線零售商做過(guò)許多類似的研究表明, 網(wǎng)站的加載時(shí)間和網(wǎng)站訂單的完成有著直接的關(guān)系.
為什么keep alive有著如此巨大的影響, 應(yīng)該是顯而易見(jiàn)的, 那就是你避免為所有的HTTP請(qǐng)求創(chuàng)建各自的連接, 這是非常低效的. 也許你不需要把keepalive-timeout設(shè)置為65, 但是10-20應(yīng)該是比較通用的選擇,正如上面一段所說(shuō), Nginx會(huì)很好的處理這方面.
tcp_nodelay 和 tcp_nopush
這兩個(gè)指令也許是最難理解的nginx配置, 他們對(duì)于nginx的影響在網(wǎng)絡(luò)的較低層. 你可以簡(jiǎn)單的認(rèn)為這些指令決定了操作系統(tǒng)如何處理網(wǎng)絡(luò)緩存和他們何時(shí)將這些緩存輸出到最終用戶(客戶端). 我只能建議大家如果你之前不了解這些概念你***不要?jiǎng)铀? 他們不會(huì)顯著的改善或者改變性能, 所以***使用他們的默認(rèn)值.
硬件限制
因?yàn)槲覀円幚韓ginx帶來(lái)的所有可能的限制, 所以我們現(xiàn)在需要弄清楚如何有效的利用我們的服務(wù)器.為了做到這點(diǎn)我們需要看一下硬件層面的東西,由于大部分服務(wù)器瓶頸都會(huì)發(fā)生在這里.
一般服務(wù)器主要還有3個(gè)方面的瓶頸. CPU,內(nèi)存和IO. Nginx在CPU的利用方面是非常高效的, 所以我會(huì)坦白的告訴你這不會(huì)成為瓶頸. 同樣nginx在使用內(nèi)存方面也是很高效的,這也不會(huì)成為瓶頸. 現(xiàn)在只剩下IO這個(gè)服務(wù)器瓶頸的罪魁禍?zhǔn)琢?(搞得像找罪犯一樣)
如果你經(jīng)常使用服務(wù)器,那么你可能經(jīng)歷過(guò)這樣認(rèn)識(shí)。硬盤驅(qū)動(dòng)器是真的,真的很慢。從硬盤驅(qū)動(dòng)器讀取可能是對(duì)服務(wù)器最昂貴的操作. 所以自然得出的結(jié)論是,為了避免IO瓶頸, 我們需要大量的減少nginx對(duì)硬盤驅(qū)動(dòng)器的讀寫.
要做到這一點(diǎn),我們可以通過(guò)修改Nginx的行為,以減少磁盤寫操作,以及確保對(duì)nginx的內(nèi)存限制,允許它避免磁盤訪問(wèn)。
Access Logs
默認(rèn)情況下,Nginx的每個(gè)請(qǐng)求都會(huì)記錄在磁盤上的日志文件中,你可以使用這個(gè)方法進(jìn)行統(tǒng)計(jì),安全問(wèn)題檢查等, 帶著這會(huì)在一定程度上帶來(lái)IO使用成本. 如果你不打算用這些訪問(wèn)日志來(lái)做一些檢查或其他用途, 你可以直接關(guān)閉它以避免對(duì)磁盤寫操作, 但是如果你需要訪問(wèn)日志,你可以考慮保存日志到內(nèi)存中.這將會(huì)比直接寫到磁盤上快很多,并且明顯減少IO的使用.
如果你只打算使用訪問(wèn)日志進(jìn)行統(tǒng)計(jì),你可以考慮使用其他的比如google analytics來(lái)取代(ga和access log還是有區(qū)別的 不能簡(jiǎn)單的取代哦),或者你只記錄訪問(wèn)請(qǐng)求的部分信息而不是全部.
Error Logs
我內(nèi)心小小的掙扎了一把,我是否要在這里闡述這個(gè)error log 指令呢,因?yàn)橐苍S你根本不希望關(guān)閉error log, 特別是考慮到實(shí)際應(yīng)用中錯(cuò)誤日志的量會(huì)很少. 但是考慮到這里指令有一個(gè)小小的地方需要引起大家注意, 錯(cuò)誤日志的等級(jí)參數(shù)你是可以指定的, 如果你指定的太低了他會(huì)記錄404錯(cuò)誤甚至是debug信息. 在實(shí)際的應(yīng)用中可以將它設(shè)置為warn級(jí)別,將會(huì)是綽綽有余的并且能降低IO.
Open File Cache
?從文件系統(tǒng)中讀取文件由2部分組成,打開和關(guān)閉文件. 考慮到這是一個(gè)有阻塞的操作,因此不要忽略這部分. 因此, 對(duì)于我們來(lái)說(shuō)緩存打開文件的描述符是非常好的,這就是open_file_cache指令的由來(lái). 鏈接的wiki地址里對(duì)于使用和配置它有著非常好的說(shuō)明, 所以我建議你去拜讀一下.
Buffers
配置Nginx緩存的大小是一個(gè)非常重要的事情. 如果緩存大小設(shè)置的太小, Nginx將不得不把上游(用英文upsteams會(huì)更好)的相應(yīng)結(jié)果存放到臨時(shí)的緩存文件里面,這將會(huì)同時(shí)增加IO的讀寫操作, 而且流量越大問(wèn)題越多.
client_body_buffer_size指令用來(lái)指定處理客戶端請(qǐng)求的緩沖區(qū)大小,?這個(gè)代表了訪問(wèn)請(qǐng)求的body. 這是用來(lái)處理POST的數(shù)據(jù),也就是通過(guò)提交表單,文件上傳等請(qǐng)求的數(shù)據(jù). 如果你需要處理很多大的POST請(qǐng)求的,你必須確保緩存區(qū)要設(shè)置的足夠大.
fastcgi_buffers?和?proxy_buffers?指令用來(lái)處理上流(upstream)的響應(yīng)結(jié)果, 也就是PHP Apache等.它的概念其實(shí)和上面提到的差不多, 如果緩沖區(qū)不足夠大數(shù)據(jù)將在返回給用戶使用之前被保存到磁盤上. 注意Nginx將這個(gè)buffer數(shù)據(jù)同步的傳輸給客戶端之前,有一個(gè)緩存上限, 保存到磁盤也同樣受限. 這個(gè)上線是通過(guò)fastcgi_max_temp_file_size和proxy_max_temp_file_size來(lái)設(shè)置的. 另外對(duì)于代理的連接你也可以通過(guò)把proxy_buffering設(shè)置成off來(lái)徹底的關(guān)閉緩存.(通常這不是一個(gè)好辦法).
徹底移除磁盤IO
***的減少磁盤IO的方法無(wú)疑是不使用磁盤, 如果你的的應(yīng)用只有少量的數(shù)據(jù)傳輸,你可以將數(shù)據(jù)都放入內(nèi)存,這樣就可以徹底不用考慮磁盤IO的阻塞了. 當(dāng)然默認(rèn)情況下你的操作系統(tǒng)也會(huì)緩存頻繁訪問(wèn)的磁盤扇區(qū), 所以內(nèi)存越大磁盤的IO就會(huì)用到的越少. 這就意味著你可以通過(guò)增加內(nèi)存來(lái)解決IO的瓶頸. 數(shù)據(jù)量越多,需要的內(nèi)存越大.
網(wǎng)絡(luò)IO
為了好玩,我們假設(shè)你有了足夠大的內(nèi)存來(lái)緩存你的所有數(shù)據(jù). 這意味著理論上你的IO讀速度達(dá)到了3-6gbps. 但是你沒(méi)有那么快的網(wǎng)絡(luò)通道. 不幸的是,我們可以優(yōu)化的網(wǎng)絡(luò)IO是有限的,我們要通過(guò)網(wǎng)絡(luò)傳輸數(shù)據(jù),所以還將受制于網(wǎng)絡(luò)IO. 唯一真正有效的方法是盡量減少數(shù)據(jù)量或壓縮。
幸運(yùn)的是Nginx提供了gzip模塊, 它可以使我們?cè)趯?shù)據(jù)傳輸給客戶端之前壓縮它, 這將大大減少數(shù)據(jù)的大小. 一般來(lái)說(shuō) gzip_comp_level的值不會(huì)在性能方面有多大的差別,設(shè)為為4-5即可. 一味的增加它是沒(méi)有意義的只是浪費(fèi)的CPU的周期.
你也可以通過(guò)一些javascript和css縮小工具來(lái)減少傳輸文件大小. 但這些不是和Nginx很相關(guān)所以我相信你通過(guò)google可以獲取更多的相關(guān)信息.
詳細(xì)出處參考:http://www.nginx.cn/821.html