nginx的優化

提及nginx的調優,壞消息是事實上沒有方法能很大程度優化nginx,不存在一個"神奇的"設置選項能夠將負載下降到原來的一半或者可讓PHP運行速度加倍。不過接下來是好消息,nginx自己已經優化的足夠好了!其實相比apache,最大的優化在你敲入"apt-get install","yum install"或者"make install"的時候已經產生了,呵呵。javascript

    那麼怎麼還要說到nginx調優這個話題呢?php

    一個緣由是由於nginx有不少的配置選項,這些選項會影響nginx的行爲。可是,這些選項的默認值並非徹底針對高負載這種情況優化的,因此須要調整。css

    另外一個緣由是nginx所運行的OS的設置也會影響nginx的運行,想要達到理想的運行效果,也須要調整。html

    咱們下面就來分別分析一下相關的問題。java

 

    1、操做系統的限制node

 

   1.操做系統自己linux

    nginx能夠運行在Linux, MacOS, FreeBSD, Solaris, Windows等衆多平臺上,這些平臺都有各自的高性能event polling方法,不過nginx只支持其中的4種。通常來講,運行在freebsdlinuxMacOS,Solaris上性能不會有很巨大的差異,全部選擇你本身熟悉的OS比要選擇所謂"絕對優化"的,可是不熟悉的OS更加劇要。不過,windows是一個例外,在生產環境中,千萬不要把nginx運行在windows上。由於windows有本身的event polling方法,而nginx的做者明確說明不支持該方法。nginx

    nginx中,能夠在配置文件中指定所使用的event polling模型,指令以下:web

  

    use epoll;  Linux系統算法

    use kqueueFreeBSD系統

 

    2.`ulimit -a`命令所列出來的這些參數

    這些參數是nginx沒法超越的。例如,在許多系統中,默認容許打開的最大文件數爲1024,若是nginx運行在這個環境下,那麼當流量大時就會出現(24: Too many open files) 錯誤。而nginx的處理能力遠不止1024,所以這個參數必須調整。

 

    2、nginx自身的限制

 

    1.編譯優化

   

    默認的nginx編譯選項是用debug模式(-g)的(debug模式會插入不少跟蹤和ASSERT之類),編譯之後一個nginx可執行文件有好幾MB。去掉nginx的debug模式編譯,編譯之後只有幾百KB

    在源碼auto/cc/gcc中,在最後幾行中找到以下內容:

 

        # debug

        CFLAGS=」$CFLAGS -g」

 

    CFLAGS這一行刪除或者註釋掉,而後再編譯便可。

 

    另外,若是隻是把nginx做爲web server,那麼能夠禁用一些用不到的modules,能夠減小內存footprint,提升服務器性能。

    ./configure --prefix=/webserver/nginx --without-mail_pop3_module --without-mail_imap_module  --without-mail_smtp_module --with-http_ssl_module  --with-http_stub_status_module  --with-http_gzip_static_module

 

    2.Worker Processes

    worker process是整個nginx的關鍵,一旦主進程綁定到了指定的IP/Port上之後,主進程會使用指定的用戶派生出worker process,這些worker process會處理全部的用戶請求。worker process不是多線程的,不須要將每一個connection在不一樣CPU內核間切換,所以運行多個worker process是必然的,一般每一個CPU core對應一個worker process。一般,若是超過4worker process,那麼CPU確定不會成爲瓶頸了,由於在CPU成爲瓶頸以前,nginx的其餘部分確定已經不行了。


cat /proc/cpuinfo |grep 'core id'

 

    3.Worker Connections

    worker connctions是一個有點"怪異"的概念,我不肯定這個指令的確切目的。可是能夠肯定的是這個指令能夠有效的限制每一個worker process在同一時間能夠維護多少個鏈接。若是非要我猜的話,我認爲這個指令是一個保險機制,爲了防止錯誤配置的keep-alive耗盡可用端口。

    在默認配製文件中,worker connections的值是1024。一般一個瀏覽器會針對一個站點打開2個鏈接,那麼最大能夠併發服務的用戶數量爲512個。這個數字看起來不小了,可是考慮到keep-alive默認的timeout值是65,那麼意味着其實咱們每秒只能處理8connection。顯然這個數字超過了大多數人的需求,尤爲是當咱們使用2-4worker process的時候。可是對於大流量的站點,而且打開了keep-alvie,那麼應該時刻考慮到這一點。

    當考慮worker connections的值的時候,其實很簡單,流量增長就增長這個值。2048對於絕大多數人應該夠用了,不過若是你的站點真的增加這麼快的話,那麼最大該設置多大,只有你本身嘗試了。

 

    4.CPU Affinity

    設置CPU affinity的意思是告訴nginx,每一個worker process應該使用哪個CPU core,指定之後該worker process只會使用你指定的那個CPU core。請當心的作這個配置,由於OSCPU調度器在處理負載均衡方面遠比人類作的更好。若是你確實認爲你須要在CPU調度器層面作優化的話,你能夠選擇不一樣的CPU調度器,不過你須要清楚的知道你本身在幹什麼,若是不知道,不要碰這個配置。

 

    5.Keep Alive

    keep alive是一個HTTP的特性,其容許用戶agent(瀏覽器)和服務器之間保持鏈接,以便其餘請求共用或者直到指定的timeout時間到達。這個特性事實上並不會改善咱們的nginx服務器性能,由於nginx本身能夠很是好的處理空閒鏈接。nginx做者指出,處理10000個空閒鏈接只耗費2.5MB的內存。

    在這裏提到keep alive的目的很簡單。keep alive對於終端用戶感受到的等待時間影響是巨大的。若是你的站點看起來載入很快,那麼用戶會很開心。Amazon作過調查,用戶感受的等待時間和最終業務成交量之間有直接的關係。

    keep alive能夠避免在建立HTTP鏈接過程當中許多無用操做,所以它的做用才如此明顯。通常咱們不須要65這麼大的timeout值,但推薦你將這個值設置在10-20之間。

 

    keepalive_timeout 15

 

    6.tcp_nodelay and tcp_nopush

    這兩個參數的用途很難理解,由於它們在很底層的網絡部分影響nginx。一個簡單膚淺的解釋是這兩個指令控制OS如何處理網絡緩衝,什麼時候將他們刷新給最終用戶。由於這兩個參數不會明顯提升或改變任何事情,若是你不明白這兩個參數的含義,那我建議你不用碰它,保持默認值就行了。

 

 

    3、硬件的限制

    上邊已經討論了OSnginx自己的一些限制,如今讓咱們看看怎麼把服務器的性能壓榨到底。

    服務器上能成爲瓶頸的就CPU,內存和IO。對於nginx來講,CPU和內存都不會是瓶頸。所以瓶頸只會產生在IO部分。硬盤相對於CPU和內存來講,是很是很是慢的設備。硬盤讀取和寫入是很是耗時的操做,所以咱們須要儘可能減小nginx對硬盤的讀寫操做。

 

    1.Access log

    nginx默認會將每一個請求寫入到日誌文件中,日誌能夠用來審計和統計。可是記錄日誌的操做會帶來IO開銷。若是你不須要記錄日誌,直接關閉這個選項就好。若是須要記錄日誌,最好將日誌記錄到內存中,而後按期將日誌轉儲到磁盤上。這樣能夠避免頻繁磁盤IO操做,極大提升性能。

 

    access_log off;

 

    2.Error log

    對於error log,其實不該該關閉的。可是爲了下降磁盤IO操做,能夠調整error log的級別,將這個參數設置成"warn"級別應該足夠了,而且也不會產生很大的IO

 

    3.Open File Cache

    從文件系統讀取數據包含文件打開和關閉操做,這部分也是磁盤塊操做。爲了減小這部分操做,能夠緩存打開的文件描述符。這個操做使用open file cache 實現,具體能夠參考連接中的wiki

 

    4.Buffers

    調整buffer的大小對於nginx很重要,若是buffer設置得過小,nginx將不得不把upstream服務器返回來的響應存儲在臨時文件中。這會致使同時增長磁盤讀寫操做,流量越大影響越明顯。

    client_body_buffer_size 指令指定了處理客戶端請求body部分的buffer的大小。這個通常用於處理POST數據,表單提交,文件上傳等操做。若是你要處理不少大的POST提交,那麼這個值要設置足夠大。

    client_header_buffer_size 指令指定了處理客戶端請求header部分的buffer的大小。設置成1K能知足絕大部分需求。

    client_max_body_size 指令指定了能夠接受的最大的用戶請求body大小。經過HTTP頭中的Content-Length確認,若是大小超過這個值,則客戶端會獲得「Request Entity Too Large」 (413)錯誤。

    large_client_header_buffers 指令分配用於處理從用戶那裏來的大文件頭請求的buffer的最大數量和buffer大小。請求的header不能比其中的一個buffer大,不然nginx會返回「Request URI too large」 (414)錯誤。最長的header行也必須小於一個buffer的大小,不然客戶端會獲得「Bad request」 (400)錯誤。

    fastcgi_buffersproxy_buffers 指令指定了處理upstream迴應的buffer大小,也就是PHP,Apache或其餘。上邊也說到了,若是這個buffer過小,在響應用戶以前,nginx將不得不把upstream服務器返回來的響應存儲在臨時文件中。注意,nginxbuffer是有上限的,這個上限由fastcgi_max_temp_file_sizeproxy_max_temp_file_size控制。固然也能夠經過將proxy_buffering設置成off來關閉proxy connectionsbuffer(一般不是個好主意!)

 

    示例以下:

    client_body_buffer_size 8K;
    client_header_buffer_size 1k;
    client_max_body_size 2m;
    large_client_header_buffers 2 1k;

 

    5.完全避免磁盤IO

    最完全的避免磁盤IO的方法是不使用磁盤,若是費用不是問題且數據量不大,那麼可使用ramdisk,將全部數據放到內存中。

 

    6.網絡IO

    爲了下降網絡IO,咱們使用gzip module來壓縮傳輸的數據量。設置gzip_comp_level的值爲4-5應該比較合適,若是設置更大沒什麼用處,白白浪費CPU

 

    gzip             on;
    gzip_comp_level  5;
    gzip_min_length  1000;
    gzip_proxied     expired no-cache no-store private auth;
    gzip_types       text/plain application/xml;
    gzip_disable     "MSIE [1-6]\.";

 

    4、什麼?上邊還不夠?!

 

    若是通過上述的優化仍然不能知足的要求,那麼建議你考慮增長更多的服務器吧,稍微花費一點錢買服務器,比你在這裏浪費時間微調nginx要來得更有效果。


--------

# 與系統CPU的core總數對應
worker_processes 24;
 
# nginx能夠打開的文件描述符的數量
# 一般在OS中用'ulimit -n 200000'
# 或者在/etc/security/limits.conf設置
worker_rlimit_nofile 200000;
 
# 錯誤日誌僅記錄crit以上級別
error_log /var/log/nginx/error.log crit
 
# 每一個worker process能夠最多服務多少客戶端
# (Max clients = worker_connections * worker_processes)
# "Max clients" 也受限於系統中可用的socket數量(~64k)
worker_connections 4000;
 
# 使用epoll模型
use epoll;
 
# 當nginx接到新鏈接的請求時,會盡量的接受更多的鏈接
# 若是worker_connections參數設置較低,則此參數會對nginx產生衝擊,謹慎!
multi_accept on;
 
# 緩存打開的文件描述符,參數值應該根據具體應用場景調整(不要照搬下邊的數值!)
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
 
# 緩衝log寫操做,以提升磁盤IO效率,或者直接關閉access_log
#access_log /var/log/nginx/access.log main buffer=16k;
access_log off;
 
# 調用Sendfile實現內核"zero copy"
# 通常應該打開,若是用來進行下載等應用磁盤IO重負載應用,可設置爲off,以平衡磁盤與網絡I/O處理速度
sendfile on;
 
# Tcp_nopush選項會讓nginx嘗試在一個packet內發送其HTTP響應,而不是分幀傳送
# 這對優化吞吐率頗有用處,對於在調用sendfile函數前prepending headers也有做用
tcp_nopush on;
 
# 不緩衝data-sends(禁用Nagle算法). Good for sending frequent small bursts of data in real time.
tcp_nodelay on;
 
# keep-alive鏈接的超時時間,server會在此時間以後關閉鏈接
keepalive_timeout 15;
 
# client的請求能夠轉換成keep-alive鏈接的數量,若是爲了性能測試,能夠設置的高一些,默認100
#keepalive_requests 100000;
 
# 容許server在client中止響應之後關閉鏈接,釋放分配給該鏈接的內存
reset_timedout_connection on;
 
# 若是client對於body的請求超過這個時間,則發送"request timed out"響應,默認60秒
# 防範慢查詢攻擊
client_body_timeout 10;
 
# 若是client中止讀取數據, 在此時間之後釋放該鏈接,默認是60秒
send_timeout 2;
 
# 打開gzip壓縮,減小數據傳輸量
gzip on;
gzip_static on;
gzip_comp_level 9;
gzip_min_length 1400;
gzip_vary  on;
gzip_http_version 1.1;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript image/gif image/jpeg application/x-javascript application/xml;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";

---------------

--------基本的nginx.conf----

user  nginx;
worker_processes 24;

error_log  /var/log/nginx/error.log crit;
pid        /var/run/nginx.pid;

events {
    worker_connections  2048;
    use epoll;
    multi_accept on;
}

worker_rlimit_nofile 200000;

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main buffer=16k;

    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;

    open_file_cache max=200000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    client_body_buffer_size 8K;
    client_header_buffer_size 1k;
    client_max_body_size 2m;
    large_client_header_buffers 2 1k;

    keepalive_timeout  15;
    reset_timedout_connection on;
    client_body_timeout 10;
    send_timeout 2;

    gzip on;
    gzip_static on;  
    gzip_comp_level 9;
    gzip_min_length 1400;
    gzip_vary  on;
    gzip_http_version 1.1;  
    gzip_proxied expired no-cache no-store private auth;
    gzip_types text/plain text/css text/xml text/javascript image/gif image/jpeg application/x-javascript application/xml;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";

    include /etc/nginx/conf.d/*.conf;
}

 

防止php文件解析漏洞

# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
    # Zero-day exploit defense.
    # http://forum.nginx.org/read.php?2,88845,page=3
    # Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
    # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine.  And then cross your fingers that you won't get hacked.

    try_files $uri =404;

    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini

    include fastcgi_params;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    # fastcgi_intercept_errors on;
    # With php5-cgi alone:
    # fastcgi_pass 127.0.0.1:9000;
    # With php5-fpm:

    fastcgi_pass unix:/var/run/php5-fpm.sock;
}

 

php-fpm中的配置,與nginx 的fastcgi_pass的路徑一致便可,目錄要有相應讀寫權限 ; Note: This value is mandatory. listen = /var/run/php5-fpm.sock

相關文章
相關標籤/搜索