天天看點

《深入了解Nginx:子產品開發與架構解析》一1.3 準備工作

由于linux具有免費、使用廣泛、商業支援越來越完善等特點,本書将主要針對linux上運作的nginx來進行介紹。需要說明的是,本書不是使用手冊,而是介紹nginx作為web伺服器的設計思想,以及如何更有效地使用nginx達成目的,而這些内容在各作業系統上基本是相通的(除了第9章關于事件驅動方式以及第14章的程序間同步方式在類unix作業系統上略有不同以外)。

首先我們需要一個核心為linux 2.6及以上版本的作業系統,因為linux 2.6及以上核心才支援epoll,而在linux上使用select或poll來解決事件的多路複用,是無法解決高并發壓力問題的。

我們可以使用uname -a指令來查詢linux核心版本,例如:

執行結果表明核心版本是2.6.18,符合我們的要求。

如果要使用nginx的常用功能,那麼首先需要確定該作業系統上至少安裝了如下軟體。

(1)gcc編譯器

gcc(gnu compiler collection)可用來編譯c語言程式。nginx不會直接提供二進制可執行程式(1.2.x版本中已經開始提供某些作業系統上的二進制安裝包了,不過,本書探讨如何開發nginx子產品是必須通過直接編譯源代碼進行的),這有許多原因,本章後面會詳述。我們可以使用最簡單的yum方式安裝gcc,例如:

gcc是必需的編譯工具。在第3章會提到如何使用c++來編寫nginx http子產品,這時就需要用到g++編譯器了。g++編譯器也可以用yum安裝,例如:

linux上有許多軟體安裝方式,yum隻是其中比較友善的一種,其他方式這裡不再贅述。

(2)pcre庫

pcre(perl compatible regular expressions,perl相容正規表達式)是由philip hazel開發的函數庫,目前為很多軟體所使用,該庫支援正規表達式。它由regex演化而來,實際上,perl正規表達式也是源自于henry spencer寫的regex。

如果我們在配置檔案nginx.conf裡使用了正規表達式,那麼在編譯nginx時就必須把pcre庫編譯進nginx,因為nginx的http子產品要靠它來解析正規表達式。當然,如果你确認不會使用正規表達式,就不必安裝它。其yum安裝方式如下:

pcre-devel是使用pcre做二次開發時所需要的開發庫,包括頭檔案等,這也是編譯nginx所必須使用的。

(3)zlib庫

zlib庫用于對http包的内容做gzip格式的壓縮,如果我們在nginx.conf裡配置了gzip on,并指定對于某些類型(content-type)的http響應使用gzip來進行壓縮以減少網絡傳輸量,那麼,在編譯時就必須把zlib編譯進nginx。其yum安裝方式如下:

同理,zlib是直接使用的庫,zlib-devel是二次開發所需要的庫。

(4)openssl開發庫

如果我們的伺服器不隻是要支援http,還需要在更安全的ssl協定上傳輸http,那麼就需要擁有openssl了。另外,如果我們想使用md5、sha1等散列函數,那麼也需要安裝它。其yum安裝方式如下:

上面所列的4個庫隻是完成web伺服器最基本功能所必需的。

nginx是高度自由化的web伺服器,它的功能是由許多子產品來支援的。而這些子產品可根據我們的使用需求來定制,如果某些子產品不需要使用則完全不必理會它。同樣,如果使用了某個子產品,而這個子產品使用了一些類似zlib或openssl等的第三方庫,那麼就必須先安裝這些軟體。

要使用nginx,還需要在linux檔案系統上準備以下目錄。

(1)nginx源代碼存放目錄

該目錄用于放置從官網上下載下傳的nginx源碼檔案,以及第三方或我們自己所寫的子產品源代碼檔案。

(2)nginx編譯階段産生的中間檔案存放目錄

該目錄用于放置在configure指令執行後所生成的源檔案及目錄,以及make指令執行後生成的目标檔案和最終連接配接成功的二進制檔案。預設情況下,configure指令會将該目錄命名為objs,并放在nginx源代碼目錄下。

(3)部署目錄

該目錄存放實際nginx服務運作期間所需要的二進制檔案、配置檔案等。預設情況下,該目錄為/usr/local/nginx。

(4)日志檔案存放目錄

日志檔案通常會比較大,當研究nginx的底層架構時,需要打開debug級别的日志,這個級别的日志非常詳細,會導緻日志檔案的大小增長得極快,需要預先配置設定一個擁有更大磁盤空間的目錄。

由于預設的linux核心參數考慮的是最通用的場景,這明顯不符合用于支援高并發通路的web伺服器的定義,是以需要修改linux核心參數,使得nginx可以擁有更高的性能。

在優化核心時,可以做的事情很多,不過,我們通常會根據業務特點來進行調整,當nginx作為靜态web内容伺服器、反向代理伺服器或是提供圖檔縮略圖功能(實時壓縮圖檔)的伺服器時,其核心參數的調整都是不同的。這裡隻針對最通用的、使nginx支援更多并發請求的tcp網絡參數做簡單說明。

首先,需要修改/etc/sysctl.conf來更改核心參數。例如,最常用的配置:

然後執行sysctl -p指令,使上述修改生效。

上面的參數意義解釋如下:

file-max:這個參數表示程序(比如一個worker程序)可以同時打開的最大句柄數,這個參數直接限制最大并發連接配接數,需根據實際情況配置。

tcp_tw_reuse:這個參數設定為1,表示允許将time-wait狀态的socket重新用于新的tcp連接配接,這對于伺服器來說很有意義,因為伺服器上總會有大量time-wait狀态的連接配接。

tcp_keepalive_time:這個參數表示當keepalive啟用時,tcp發送keepalive消息的頻度。預設是2小時,若将其設定得小一些,可以更快地清理無效的連接配接。

tcp_fin_timeout:這個參數表示當伺服器主動關閉連接配接時,socket保持在fin-wait-2狀态的最大時間。

tcp_max_tw_buckets:這個參數表示作業系統允許time_wait套接字數量的最大值,如果超過這個數字,time_wait套接字将立刻被清除并列印警告資訊。該參數預設為180 000,過多的time_wait套接字會使web伺服器變慢。

tcp_max_syn_backlog:這個參數表示tcp三次握手建立階段接收syn請求隊列的最大長度,預設為1024,将其設定得大一些可以使出現nginx繁忙來不及accept新連接配接的情況時,linux不至于丢失用戶端發起的連接配接請求。

ip_local_port_range:這個參數定義了在udp和tcp連接配接中本地(不包括連接配接的遠端)端口的取值範圍。

net.ipv4.tcp_rmem:這個參數定義了tcp接收緩存(用于tcp接收滑動視窗)的最小值、預設值、最大值。

net.ipv4.tcp_wmem:這個參數定義了tcp發送緩存(用于tcp發送滑動視窗)的最小值、預設值、最大值。

netdev_max_backlog:當網卡接收資料包的速度大于核心處理的速度時,會有一個隊列儲存這些資料包。這個參數表示該隊列的最大值。

rmem_default:這個參數表示核心套接字接收緩存區預設的大小。

wmem_default:這個參數表示核心套接字發送緩存區預設的大小。

rmem_max:這個參數表示核心套接字接收緩存區的最大大小。

wmem_max:這個參數表示核心套接字發送緩存區的最大大小。

注意 滑動視窗的大小與套接字緩存區會在一定程度上影響并發連接配接的數目。每個tcp連接配接都會為維護tcp滑動視窗而消耗記憶體,這個視窗會根據伺服器的處理速度收縮或擴張。

參數wmem_max的設定,需要平衡實體記憶體的總大小、nginx并發處理的最大連接配接數量(由nginx.conf中的worker_processes和worker_connections參數決定)而确定。當然,如果僅僅為了提高并發量使伺服器不出現out of memory問題而去降低滑動視窗大小,那麼并不合适,因為滑動視窗過小會影響大資料量的傳輸速度。rmem_default、wmem_default、rmem_max、wmem_max這4個參數的設定需要根據我們的業務特性以及實際的硬體成本來綜合考慮。

tcp_syncookies:該參數與性能無關,用于解決tcp的syn攻擊。

本書編寫時的nginx最新穩定版本為1.0.14(如圖1-2所示),本書後續部分都将以此版本作為基準。當然,本書将要說明的nginx核心代碼一般不會有改動(否則大量第三方子產品的功能就無法保證了),即使下載下傳其他版本的nginx源碼包也不會影響閱讀本書。

《深入了解Nginx:子產品開發與架構解析》一1.3 準備工作