Nginx性能優化

1、編譯安裝過程優化

一、減少Nginx編譯後的文件大小javascript

在編譯Nginx時,默認以debug模式進行,而在debug模式下會插入不少跟蹤和ASSERT之類的信息,編譯完成後,一個Nginx要有好幾兆字節。而在編譯前取消Nginx的debug模式,編譯完成後Nginx只有幾百千字節。所以能夠在編譯以前,修改相關源碼,取消debug模式。具體方法以下:php

# debug  css

CFLAGS=」$CFLAGS -g」 html

註釋掉或刪掉這兩行,便可取消debug模式。java

2.爲特定的CPU指定CPU類型編譯優化mysql

在編譯Nginx時,默認的GCC編譯參數是「-O」,要優化GCC編譯,可使用如下兩個參數:linux

--with-cc-opt='-O3' nginx

--with-cpu-opt=CPU  #爲特定的 CPU 編譯,有效的值包括:pentium, pentiumpro, pentium3, pentium4, athlon, opteron, amd64, sparc32, sparc64, ppc64 web

 

要肯定CPU類型,能夠經過以下命令:sql

[root@localhost home]#cat /proc/cpuinfo | grep "model name" 

二. 利用TCMalloc優化Nginx的性能

      TCMalloc的全稱爲Thread-Caching Malloc,是谷歌開發的開源工具google-perftools中的一個成員。與標準的glibc庫的Malloc相比,TCMalloc庫在內存分配效率和速度上要高不少,這在很大程度上提升了服務器在高併發狀況下的性能,從而下降了系統的負載。下面簡單介紹如何爲Nginx添加TCMalloc庫支持。

      要安裝TCMalloc庫,須要安裝libunwind(32位操做系統不須要安裝)和google-perftools兩個軟件包,libunwind庫爲基於64位CPU和操做系統的程序提供了基本函數調用鏈和函數調用寄存器功能。下面介紹利用TCMalloc優化Nginx的具體操做過程。

1.安裝libunwind庫

能夠從http://download.savannah.gnu.org/releases/libunwind下載相應的libunwind版本,這裏下載的是libunwind-0.99-alpha.tar.gz。安裝過程以下:

[root@localhost home]#tar zxvf libunwind-0.99-alpha.tar.gz  

[root@localhost home]# cd libunwind-0.99-alpha/  

[root@localhost libunwind-0.99-alpha]#CFLAGS=-fPIC ./configure  

[root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC  

[root@localhost libunwind-0.99-alpha]#make CFLAGS=-fPIC install

2.安裝google-perftools

能夠從http://google-perftools.googlecode.com下載相應的google-perftools版本,這裏下載的是google-perftools-1.8.tar.gz。安裝過程以下:

[root@localhost home]#tar zxvf google-perftools-1.8.tar.gz  

[root@localhost home]#cd google-perftools-1.8/  

[root@localhost google-perftools-1.8]# ./configure  

[root@localhost google-perftools-1.8]#make && make install  

[root@localhost google-perftools-1.8]#echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf  

[root@localhost google-perftools-1.8]# ldconfig

至此,google-perftools安裝完成。

3.從新編譯Nginx

爲了使Nginx支持google-perftools,須要在安裝過程當中添加「–with-google_perftools_module」選項從新編譯Nginx。安裝代碼以下:

[root@localhostnginx-0.7.65]#./configure  --with-google_perftools_module --with-http_stub_status_module  --prefix=/opt/nginx  

[root@localhost nginx-0.7.65]#make  

[root@localhost nginx-0.7.65]#make install 

到這裏Nginx安裝完成。

4.爲google-perftools添加線程目錄

建立一個線程目錄,這裏將文件放在/tmp/tcmalloc下。操做以下:

[root@localhost home]#mkdir /tmp/tcmalloc  

[root@localhost home]#chmod 0777 /tmp/tcmalloc 

5.修改Nginx主配置文件

修改nginx.conf文件,在pid這行的下面添加以下代碼:

#pid        logs/nginx.pid;  

google_perftools_profiles /tmp/tcmalloc; 

接着,重啓Nginx便可完成google-perftools的加載。

6.驗證運行狀態

爲了驗證google-perftools已經正常加載,可經過以下命令查看:

[root@ localhost home]# lsof -n | grep tcmalloc        (-n : no host names

nginx      2395 nobody   9w  REG    8,8       0    1599440  /tmp/tcmalloc.2395  

nginx      2396 nobody   11w REG   8,8       0    1599443  /tmp/tcmalloc.2396  

nginx      2397 nobody   13w REG  8,8        0    1599441  /tmp/tcmalloc.2397  

nginx     2398 nobody    15w REG  8,8        0    1599442  /tmp/tcmalloc.2398 

因爲在Nginx配置文件中設置worker_processes的值爲4,所以開啓了4個Nginx線程,每一個線程會有一行記錄。每一個線程文件後面的數字值就是啓動的Nginx的pid值。

至此,利用TCMalloc優化Nginx的操做完成。

3、Nginx內核參數優化

內核參數的優化,主要是在Linux系統中針對Nginx應用而進行的系統內核參數優化。

下面給出一個優化實例以供參考。

net.ipv4.tcp_max_tw_buckets = 6000 
net.ipv4.ip_local_port_range = 1024 65000  
net.ipv4.tcp_tw_recycle = 1 
net.ipv4.tcp_tw_reuse = 1 
net.ipv4.tcp_syncookies = 1 
net.core.somaxconn = 262144 
net.core.netdev_max_backlog = 262144 
net.ipv4.tcp_max_orphans = 262144 
net.ipv4.tcp_max_syn_backlog = 262144 
net.ipv4.tcp_synack_retries = 1 
net.ipv4.tcp_syn_retries = 1 
net.ipv4.tcp_fin_timeout = 1 
net.ipv4.tcp_keepalive_time = 30 

將上面的內核參數值加入/etc/sysctl.conf文件中,而後執行以下命令使之生效:

[root@ localhost home]#/sbin/sysctl -p 

下面對實例中選項的含義進行介紹:

net.ipv4.tcp_max_tw_buckets :選項用來設定timewait的數量,默認是180 000,這裏設爲6000。

net.ipv4.ip_local_port_range:選項用來設定容許系統打開的端口範圍。在高併發狀況不然端口號會不夠用。

net.ipv4.tcp_tw_recycle:選項用於設置啓用timewait快速回收.

net.ipv4.tcp_tw_reuse:選項用於設置開啓重用,容許將TIME-WAIT sockets從新用於新的TCP鏈接。

net.ipv4.tcp_syncookies:選項用於設置開啓SYN Cookies,當出現SYN等待隊列溢出時,啓用cookies進行處理。

net.core.somaxconn:選項的默認值是128, 這個參數用於調節系統同時發起的tcp鏈接數,在高併發的請求中,默認的值可能會致使連接超時或者重傳,所以,須要結合併發請求數來調節此值。

net.core.netdev_max_backlog:選項表示當每一個網絡接口接收數據包的速率比內核處理這些包的速率快時,容許發送到隊列的數據包的最大數目

net.ipv4.tcp_max_orphans:選項用於設定系統中最多有多少個TCP套接字不被關聯到任何一個用戶文件句柄上。若是超過這個數字,孤立鏈接將當即被複位並打印出警告信息。這個限制只是爲了防止簡單的DoS攻擊。不能過度依靠這個限制甚至人爲減少這個值,更多的狀況下應該增長這個值。

net.ipv4.tcp_max_syn_backlog:選項用於記錄那些還沒有收到客戶端確認信息的鏈接請求的最大值。對於有128MB內存的系統而言,此參數的默認值是1024,對小內存的系統則是128。

net.ipv4.tcp_synack_retries參數的值決定了內核放棄鏈接以前發送SYN+ACK包的數量。

net.ipv4.tcp_syn_retries選項表示在內核放棄創建鏈接以前發送SYN包的數量。

net.ipv4.tcp_fin_timeout選項決定了套接字保持在FIN-WAIT-2狀態的時間。默認值是60秒。正確設置這個值很是重要,有時即便一個負載很小的Web服務器,也會出現大量的死套接字而產生內存溢出的風險。

net.ipv4.tcp_syn_retries選項表示在內核放棄創建鏈接以前發送SYN包的數量。

若是發送端要求關閉套接字,net.ipv4.tcp_fin_timeout選項決定了套接字保持在FIN-WAIT-2狀態的時間。接收端能夠出錯並永遠不關閉鏈接,甚至意外宕機。

net.ipv4.tcp_fin_timeout的默認值是60秒。須要注意的是,即便一個負載很小的Web服務器,也會出現由於大量的死套接字而產生內存溢出的風險。FIN-WAIT-2的危險性比FIN-WAIT-1要小,由於它最多隻能消耗1.5KB的內存,可是其生存期長些。

net.ipv4.tcp_keepalive_time選項表示當keepalive啓用的時候,TCP發送keepalive消息的頻度。默認值是2(單位是小時)。

4、PHP-FPM的優化

若是您高負載網站使用PHP-FPM管理FastCGI,這些技巧也許對您有用:

1)增長FastCGI進程數

把PHP FastCGI子進程數調到100或以上,在4G內存的服務器上200就能夠建議經過壓力測試獲取最佳值。

2)增長 PHP-FPM打開文件描述符的限制

標籤rlimit_files用於設置PHP-FPM對打開文件描述符的限制,默認值爲1024。這個標籤的值必須和Linux內核打開文件數關聯起來,例如,要將此值設置爲65 535,就必須在Linux命令行執行「ulimit -HSn 65536」。

       而後 增長 PHP-FPM打開文件描述符的限制:
     # vi /path/to/php-fpm.conf
    找到「<valuename="rlimit_files">1024</value>」
把1024更改成 4096或者更高.
重啓 PHP-FPM.

       ulimit -n 要調整爲65536甚至更大。如何調這個參數,能夠參考網上的一些文章。命令行下執行 ulimit -n65536便可修改。若是不能修改,須要設置  /etc/security/limits.conf,加入

* hard nofile65536

* soft nofile 65536

 

         3)適當增長max_requests

    標籤max_requests指明瞭每一個children最多處理多少個請求後便會被關閉,默認的設置是500。

    <value name="max_requests"> 500 </value>

 

5、nginx.conf的參數優化 

nginx要開啓的進程數 通常等於cpu的總核數 其實通常狀況下開4個或8個就能夠。

每一個nginx進程消耗的內存10兆的模樣

worker_cpu_affinity
僅適用於linux,使用該選項能夠綁定worker進程和CPU(2.4內核的機器用不了)

假如是8 cpu 分配以下:
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000

00100000 01000000 10000000

nginx可使用多個worker進程,緣由以下:

to use SMP 
to decrease latency when workers blockend on disk I/O 
to limit number of connections per process when select()/poll() is

used The worker_processes and worker_connections from the event sections

allows you to calculate maxclients value: k max_clients = worker_processes * worker_connections

 

worker_rlimit_nofile 102400;

每一個nginx進程打開文件描述符最大數目 配置要和系統的單進程打開文件數一致,linux 2.6內核下開啓文件打開數爲65535,worker_rlimit_nofile就相應應該填寫65535 nginx調度時分配請求到進程並非那麼的均衡,假如超過會返回502錯誤。我這裏寫的大一點

use epoll

Nginx使用了最新的epoll(Linux 2.6內核)和kqueue(freebsd)網絡I/O模型,而Apache則使用的是傳統的select模型。

處理大量的鏈接的讀寫,Apache所採用的select網絡I/O模型很是低效。在高併發服務器中,輪詢I/O是最耗時間的操做 目前Linux下可以承受高併發

訪問的Squid、Memcached都採用的是epoll網絡I/O模型。

worker_connections 65535;
每一個工做進程容許最大的同時鏈接數 (Maxclient = work_processes * worker_connections)

keepalive_timeout 75

keepalive超時時間

這裏須要注意官方的一句話:
The parameters can differ from each other. Line Keep-Alive:

timeout=time understands Mozilla and Konqueror. MSIE itself shuts

keep-alive connection approximately after 60 seconds.

 

client_header_buffer_size 16k
large_client_header_buffers 4 32k

客戶請求頭緩衝大小 
nginx默認會用client_header_buffer_size這個buffer來讀取header值,若是header過大,它會使用large_client_header_buffers來讀取

若是設置太小HTTP頭/Cookie過大 會報400 錯誤 nginx 400 bad request
求行若是超過buffer,就會報HTTP 414錯誤(URI Too Long) nginx接受最長的HTTP頭部大小必須比其中一個buffer大,不然就會報400的HTTP錯誤(Bad Request)。

open_file_cache max 102400

使用字段:http, server, location 這個指令指定緩存是否啓用,若是啓用,將記錄文件如下信息: ·打開的文件描述符,大小信息和修改時間. ·存在的目錄信息. ·在搜索文件過程當中的錯誤信息 -- 沒有這個文件,沒法正確讀取,參考open_file_cache_errors 指令選項:
·max - 指定緩存的最大數目,若是緩存溢出,最長使用過的文件(LRU)將被移除
例: open_file_cache max=1000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on;

open_file_cache_errors
語法:open_file_cache_errors on | off 默認值:open_file_cache_errors off 使用字段:http, server, location 這個指令指定是否在搜索一個文件是記錄cache錯誤.

open_file_cache_min_uses

語法:open_file_cache_min_uses number 默認值:open_file_cache_min_uses 1 使用字段:http, server, location 這個指令指定了在open_file_cache指令無效的參數中必定的時間範圍內可使用的最小文件數,如 果使用更大的值,文件描述符在cache中老是打開狀態.
open_file_cache_valid

語法:open_file_cache_valid time 默認值:open_file_cache_valid 60 使用字段:http, server, location 這個指令指定了什麼時候須要檢查open_file_cache中緩存項目的有效信息.


開啓gzip
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;

緩存靜態文件:

location ~* ^.+\.(swf|gif|png|jpg|js|css)$ {
root /usr/local/ku6/ktv/show.ku6.com/;
expires 1m;

 

6、錯誤排查

一、Nginx 502 Bad Gateway

php-cgi進程數不夠用、php執行時間長(mysql慢)、或者是php-cgi進程死掉,都會出現502錯誤

通常來講Nginx 502 Bad Gateway和php-fpm.conf的設置有關,而Nginx 504 Gateway Time-out則是與nginx.conf的設置有關

1)、查看當前的PHP FastCGI進程數是否夠用:

netstat -anpo | grep "php-cgi" | wc -l

  若是實際使用的「FastCGI進程數」接近預設的「FastCGI進程數」,那麼,說明「FastCGI進程數」不夠用,須要增大。

2)、部分PHP程序的執行時間超過了Nginx的等待時間,能夠適當增長

     nginx.conf配置文件中FastCGI的timeout時間,例如:

http {
    ......
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    ......
}


二、413 Request Entity Too Large
     解決:增大client_max_body_size

    client_max_body_size:指令指定容許客戶端鏈接的最大請求實體大小,它出如今請求頭部的Content-Length字段. 若是請求大於指定的值,客戶端將收到一個"Request Entity Too Large" (413)錯誤. 記住,瀏覽器並不知道怎樣顯示這個錯誤.

    php.ini中增大
post_max_size 和upload_max_filesize

3 Ngnix error.log出現:upstream sent too big header while reading response header from upstream錯誤

1)若是是nginx反向代理
   proxy是nginx做爲client轉發時使用的,若是header過大,超出了默認的1k,就會引起上述的upstream sent too big header (說白了就是nginx把外部請求給後端server,後端server返回的header  太大nginx處理不過來就致使了。

  server {
        listen       80;
        server_name  *.xywy.com ;

        large_client_header_buffers 4 16k;

        location / {

          #添加這3行 
           proxy_buffer_size 64k;
           proxy_buffers   32 32k;
           proxy_busy_buffers_size 128k;

           proxy_set_header Host $host;
           proxy_set_header X-Real-IP       $remote_addr;
           proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;

    }

}         

 

2) 若是是 nginx+PHPcgi 

  錯誤帶有 upstream: "fastcgi://127.0.0.1:9000"。就該 

  多加:

  fastcgi_buffer_size 128k;
  fastcgi_buffers 4 128k;

 

server {
        listen       80;
        server_name  ddd.com;
        index index.html index.htm index.php;
   
        client_header_buffer_size 128k;
        large_client_header_buffers 4 128k;
        proxy_buffer_size 64k;
        proxy_buffers 8 64k;
        fastcgi_buffer_size 128k;
        fastcgi_buffers 4 128k;

 

        location / {

          ......

        }

}         

 

 

7、Nginx的php漏洞

 

漏洞介紹:nginx是一款高性能的web服務器,使用很是普遍,其不只常常被用做反向代理,也能夠很是好的支持PHP的運行。80sec發現其中存在一個較爲嚴重的安全問題,默認狀況下可能致使服務器錯誤的將任何類型的文件以PHP的方式進行解析,這將致使嚴重的安全問題,使得惡意的攻擊者可能攻陷支持php的nginx服務器。


漏洞分析:nginx默認以cgi的方式支持php的運行,譬如在配置文件當中能夠以


location ~ .php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}

的方式支持對php的解析,location對請求進行選擇的時候會使用URI環境變量進行選擇,其中傳遞到後端Fastcgi的關鍵變量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name決定,而經過分析能夠看到$fastcgi_script_name是直接由URI環境變量控制的,這裏就是產生問題的點。而爲了較好的支持PATH_INFO的提取,在PHP的配置選項裏存在cgi.fix_pathinfo選項,其目的是爲了從SCRIPT_FILENAME裏取出真正的腳本名。
那麼假設存在一個http://www.80sec.com/80sec.jpg,咱們以以下的方式去訪問

http://www.80sec.com/80sec.jpg/80sec.php


將會獲得一個URI

/80sec.jpg/80sec.php

通過location指令,該請求將會交給後端的fastcgi處理,nginx爲其設置環境變量SCRIPT_FILENAME,內容爲

/scripts/80sec.jpg/80sec.php

而在其餘的webserver如lighttpd當中,咱們發現其中的SCRIPT_FILENAME被正確的設置爲

/scripts/80sec.jpg

因此不存在此問題。
後端的fastcgi在接受到該選項時,會根據fix_pathinfo配置決定是否對SCRIPT_FILENAME進行額外的處理,通常狀況下若是不對fix_pathinfo進行設置將影響使用PATH_INFO進行路由選擇的應用,因此該選項通常配置開啓。Php經過該選項以後將查找其中真正的腳本文件名字,查找的方式也是查看文件是否存在,這個時候將分離出SCRIPT_FILENAME和PATH_INFO分別爲

/scripts/80sec.jpg和80sec.php

最後,以/scripts/80sec.jpg做爲這次請求須要執行的腳本,攻擊者就能夠實現讓nginx以php來解析任何類型的文件了。

POC: 訪問一個nginx來支持php的站點,在一個任何資源的文件如robots.txt後面加上/80sec.php,這個時候你能夠看到以下的區別:

訪問http://www.80sec.com/robots.txt

HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:05:30 GMT
Content-Type: text/plain
Content-Length: 18
Last-Modified: Thu, 20 May 2010 06:26:34 GMT
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes

訪問訪問http://www.80sec.com/robots.txt/80sec.php

HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:06:49 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/5.2.6

其中的Content-Type的變化說明了後端負責解析的變化,該站點就可能存在漏洞。

漏洞廠商:http://www.nginx.org

解決方案:

咱們已經嘗試聯繫官方,可是此前你能夠經過如下的方式來減小損失

關閉cgi.fix_pathinfo爲0

或者

if ( $fastcgi_script_name ~ ..*/.*php ) {
return 403;
}

 

參考文檔:http://blog.csdn.net/hguisu/article/details/8930668

相關文章
相關標籤/搜索