nginx 的磁盤IO優化


磁盤IO優化的幾個方面

優化讀取

Sendfile 零拷貝、內存盤、SSD盤
減少寫入
AIO
增大error_log級別的日志
關閉access_log 
壓縮access_log
是否啟用proxy buffering
syslog替代本地IO
線程池 thread pool
 
 

適用於大文件的直接IO

   當磁盤文件超過size大小之后,使用directIO功能,避免Buffered IO模式下磁盤頁緩存中的拷貝消耗

Syntax: directio size | off;  #配置文件最大后表示大於大小
Default: directio off; 
Context: http, server, location







Syntax: directio_alignment size;  讀取文件緩沖區
Default: directio_alignment 512; 
Context: http, server, location

  異步IO

普通IO:當程序發起一個系統調用去讀一個文件時,程序這時會被阻塞住等待讀取到文件再次執行,這是先到內核空間發起一個read請求,開始去讀磁盤數據,讀到高速緩存(內存)里,這時喚醒進程繼續執行;寫的時候是直接寫到高速緩存(內存)里,之后自動同步

異步IO: 當用戶發起一個讀操作時,程序不會被阻塞在哪里,可以去處理其他請求

nginx指令啟用異步IO

Syntax: aio on | off | threads[=pool];  # 最后這個是線程池;調應的
Default: aio off; 
Context: http, server, location



Syntax: aio_write on | off;  #設置寫時啟用AIO;默認是關閉的;
Default: aio_write off; 
Context: http, server, location

  異步IO線程池的定義,默認未編譯--with-threads

線程池:worker進程在處理時,有一些請求可能會發生一些阻塞,這是我們就不能接受worker進程的阻塞,而是在worker進程里定義一些線程池,由線程池里的線程處理這些可能發生系統阻塞的工作;為什么會出現這樣的場景呢:因為nginx在做靜態資源服務器的時候,處理了太多的文件,因為處理文件太多,會導致文件緩存的inode失效,因為內存不夠大而導致的,一些操作大部分情況下會命中內存中緩存的。

 

定義線程池

Syntax: thread_pool name threads=number [max_queue=number];  #在靜態服務的情況下使用線程池
Default: thread_pool default threads=32 max_queue=65536; # max_queue是定義隊列最大長度;threads=32 線程池里線程個數
Context: main

  異步IO中緩存

Syntax: output_buffers number size;
Default: output_buffers 2 32k; 
Context: http, server, location

  empty_gif 模塊默認是編譯進nginx中的

 ngx_http_empty_gif_module

 功能:從前端用戶做用戶行為分析時,由於跨域等請求,前端打點的上報數據是get請求,且考慮到瀏覽器接卸DOM樹的性能消耗,所以請求透明圖片消耗最小,而1*1的gift圖片體積最小(僅43字節),故通常請求gif圖片,並在請求中把用戶行為信息上報服務器;Nginx可以在access日志中獲取到請求參數,進而統計用戶行為,但若在磁盤中讀取1x1的文件有磁盤IO消耗,empty_gif模塊將圖片放在內存中,加速了處理速度

Syntax: empty_gif;
Default: —
Context: location

  記錄日志時啟用壓縮功能

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time][if=condition]];  #[buffer=緩存大小][gzip[=壓縮比例可選1-9,數字越大壓縮的越小,話的時間越多]] [flush=最長刷新時間]
Default: access_log logs/access.log combined; 
Context: http, server, location, if in location, limit_except

  error.log 日志內容輸出到內存中

場景:開發環境下定位,若需要打開debug級別日志,但大量的debug日志引發性能問題不能容忍,可以將日志輸出到內存中

配置語法

error_log memory:32m debug;

   查看中日志方法

gdb-p[worker 進程 ID ] -ex "source nginx.gdb" --batch nginx.gdb腳本內容

set $log = ngx_cycle->log 
while $log->writer != ngx_log_memory_writer 
set $log = $log->next 
end 
set $buf = (ngx_log_memory_buf_t *) $log->wdata 
dump binary memory debug_log.txt $buf->start $buf->end

  syslog協議

sendfile 零拷貝技術

 應用程序普通調用:應用程序先發起一個讀請求,從磁盤讀到內核再從內核讀到應用程序緩存里,然后程序再把緩存里的數據寫到內核的socket緩沖再進行發送

sendfile技術:程序程序只發起一個sendfile 的調用,告訴內核我要把磁盤數據從哪里開始讀讀取多少字節,然后把讀到的數據發送到那個socket套接字上

sendfile 、直接IO、異步IO同時啟用時

直接IO會禁用sendfile技術

location /video/ { 
sendfile on; 
aio on; 
directio 8m; 
}
  當文件大小超過8M時,啟用AIO與directio

  

gzip_static 模塊: ngx_http_gzip_static_module,通過--with-http_gzip_static_module啟用該模塊
功能:檢測到同名.gz文件時,response 中通過gzip相關header返回.gz文件的內容
 
Syntax: gzip_static on | off | always;    #不管客戶端是否支持壓縮我都把壓縮文件發給客戶端always ;on是會判斷客戶端是否會支持壓縮
Default: gzip_static off; Context: http, server, location

gunzip : 模塊ngx_http_gunzip_module,通過--with-http_gunzip_module啟用該模塊

功能:當客戶端不支持gzip壓縮時,且磁盤上僅有壓縮文件,則實時解壓縮並將其發送給客戶端

Syntax: gunzip on | off;
Default: gunzip off; 
Context: http, server, location




Syntax: gunzip_buffers number size;  #打開內存緩存區
Default: gunzip_buffers 32 4k|16 8k; 
Context: http, server, location

  

tcmalloc 內存分配器
 更快的內存分配器:並發能力強於glibc;並發線程數越多,性能越好 ;減少內存碎片;擅長管理小塊內存。這是谷歌提供的第三方模塊介紹:http://goog-perftools.sourceforge.net/doc/tcmalloc.html
地址:https://github.com/gperftools/gperftools/release
安裝此系統模塊
 wget https://github.com/gperftools/gperftools/releases/download/gperftools-2.7/gperftools-2.7.tar.gz
[root@python ]# tar xf gperftools-2.7.tar.gz
[root@python ]# cd gperftools-2.7/
[root@python gperftools-2.7]# ./configure 
[root@python gperftools-2.7]# make && make install
查看生成庫文件路徑/usr/local/lib/
ll /usr/local/lib/libtcmalloc.so

 

 

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM