天天看點

Nginx應用筆記(一)基礎和安裝

nginx在啟動後,會有一個master程序和多個worker程序。master程序主要用來管理worker程序,包含:接收來自外界的信号,向各worker程序發送信号,監控worker程序的運作狀态,當worker程序退出後(異常情況下),會自動重新啟動新的worker程序。而基本的網絡事件,則是放在worker程序中來處理了。多個worker程序之間是對等的,他們同等競争來自用戶端的請求,各程序互相之間是獨立的。一個請求,隻可能在一個worker程序中處理,一個worker程序,不可能處理其它程序的請求。worker程序的個數是可以設定的,一般我們會設定與機器cpu核數一緻,這裡面的原因與nginx的程序模型以及事件處理模型是分不開的。nginx的程序模型,可以由下圖來表示:

Nginx應用筆記(一)基礎和安裝

在nginx啟動後,如果我們要操作nginx,要怎麼做呢?從上文中我們可以看到,master來管理worker程序,是以我們隻需要與master程序通信就行了。master程序會接收來自外界發來的信号,再根據信号做不同的事情。是以我們要控制nginx,隻需要通過kill向master程序發送信号就行了。比如kill -hup pid,則是告訴nginx,從容地重新開機nginx,我們一般用這個信号來重新開機nginx,或重新加載配置,因為是從容地重新開機,是以服務是不中斷的。master程序在接收到hup信号後是怎麼做的呢?首先master程序在接到信号後,會先重新加載配置檔案,然後再啟動新的worker程序,并向所有老的worker程序發送信号,告訴他們可以光榮退休了。新的worker在啟動後,就開始接收新的請求,而老的worker在收到來自master的信号後,就不再接收新的請求,并且在目前程序中的所有未處理完的請求處理完成後,再退出。當然,直接給master程序發送信号,這是比較老的操作方式,nginx在0.8版本之後,引入了一系列指令行參數,來友善我們管理。比如,./nginx -s reload,就是來重新開機nginx,./nginx -s stop,就是來停止nginx的運作。如何做到的呢?我們還是拿reload來說,我們看到,執行指令時,我們是啟動一個新的nginx程序,而新的nginx程序在解析到reload參數後,就知道我們的目的是控制nginx來重新加載配置檔案了,它會向master程序發送信号,然後接下來的動作,就和我們直接向master程序發送信号一樣了。

現在,我們知道了當我們在操作nginx的時候,nginx内部做了些什麼事情,那麼,worker程序又是如何處理請求的呢?我們前面有提到,worker程序之間是平等的,每個程序,處理請求的機會也是一樣的。當我們提供80端口的http服務時,一個連接配接請求過來,每個程序都有可能處理這個連接配接,怎麼做到的呢?首先,每個worker程序都是從master程序fork過來,在master程序裡面,先建立好需要listen的socket(listenfd)之後,然後再fork出多個worker程序。所有worker程序的listenfd會在新連接配接到來時變得可讀,為保證隻有一個程序處理該連接配接,所有worker程序在注冊listenfd讀事件前搶accept_mutex,搶到互斥鎖的那個程序注冊listenfd讀事件,在讀事件裡調用accept接受該連接配接。當一個worker程序在accept這個連接配接之後,就開始讀取請求,解析請求,處理請求,産生資料後,再傳回給用戶端,最後才斷開連接配接,這樣一個完整的請求就是這樣的了。我們可以看到,一個請求,完全由worker程序來處理,而且隻在一個worker程序中處理。

1.線上安裝

$sudo apt-get install nginx

ubuntu安裝nginx之後的檔案結構為:

所有的配置檔案都在/etc/nginx下,并且每個虛拟主機已經安排在了/etc/nginx/sites-available下

啟動程式檔案在/usr/sbin/nginx

日志放在了/var/log/nginx中,分别是access.log和error.log

并已經在/etc/init.d/下建立了啟動腳本nginx

預設的虛拟主機的目錄設定在了/usr/share/nginx/www

啟動使用$sudo /etc/init.d/nginx start。

2.源代碼安裝

為了友善後面的配置,還是使用源代碼編譯的方式安裝,

nginx主要有三種版本:

mainline version

stable version

legacy versions

一般來說,線上通常使用穩定版本。目前最新的穩定版本是nginx-1.8.0,

下載下傳nginx-1.8.0.tar.gz,解壓到合适的目錄。

nginx依賴以下子產品:

gzip子產品需要 zlib 庫

rewrite子產品需要 pcre 庫

ssl 功能需要openssl庫

如果缺失上述子產品,編譯時會出錯:

the http rewrite module requires the pcre library.

1.安裝pcre

擷取pcre編譯安裝包,在http://www.pcre.org/上可以擷取目前最新的版本

解壓縮pcre-xx.tar.gz包。

進入解壓縮目錄,執行./configure。

中間提示錯誤,

configure: error: you need a c++ compiler for c++ support.

解決sudo apt-get install build-essential。

make & make install

2.安裝openssl

擷取openssl編譯安裝包,在http://www.openssl.org/source/上可以擷取目前最新的版本。

解壓縮openssl-0.9.8zg.tar.gz包。

進入解壓縮目錄,執行./config。

3.安裝zlib

擷取zlib編譯安裝包,在http://www.zlib.net/上可以擷取目前最新的版本。

解壓縮zlib-1.2.8.tar.gz包。

接下來安裝nginx,

./configure./configuremake

$make install

安裝成功之後,nginx放置在/usr/local/nginx目錄下,主要的配置檔案為conf目錄下的nginx.conf,

nginx的啟動檔案在sbin目錄下的nginx檔案。

若安裝時找不到上述依賴子產品,使用--with-openssl=<openssl_dir>、--with-pcre=<pcre_dir>、--with-zlib=<zlib_dir>指定依賴的子產品目錄。如已安裝過,此處的路徑為安裝目錄;若未安裝,則此路徑為編譯安裝包路徑,nginx将執行子產品的預設編譯安裝。

啟動nginx之後,浏覽器中輸入http://localhost可以驗證是否安裝啟動成功。

apache在處理使用者請求時采用的是程序,若采用prefork的mpms機制,apache在每個時刻都要保持8個空閑的子程序,當使用者請求過多時,開啟的程序較多,占用記憶體大,效率與nginx相比較低,每秒最多的并發連接配接請求最多不超過3000個。但是apache有個優點就是非常穩定,當一個程序死掉時,不會影響其他的使用者。而nginx在處理使用者請求時采用的是線程,而線程是共享記憶體的,nginx隻需要開啟少量程序,多個線程就可以共享程序的記憶體,占用記憶體小,nginx采用的是epoll機制(事件主動通知機制)每秒最多的并發連接配接請求理論可以達到50000個。但是nginx的缺點是,穩定性差,當一個程序死掉時,會影響到多個使用者的使用。

這得益于nginx使用了最新的epoll(linux 2.6核心)和kqueue(freebsd)網絡i/o模型,而apache則使用的是傳統的select模型。

目前linux下能夠承受高并發通路的squid、memcached都采用的是epoll網絡i/o模型。

處理大量的連接配接的讀寫,apache所采用的select網絡i/o模型非常低效。

下面用一個比喻來解析apache采用的select模型和nginx采用的epoll模型進行之間的差別:

假設你在大學讀書,住的宿舍樓有很多間房間,你的朋友要來找你。

select版宿管大媽就會帶着你的朋友挨個房間去找,直到找到你為止。

而epoll版宿管大媽會先記下每位同學的房間号,你的朋友來時,隻需告訴你的朋友你住在哪個房間即可,不用親自帶着你的朋友滿大樓找人。

如果來了10000個人,都要找自己住這棟樓的同學時,select版和epoll版宿管大媽,誰的效率更高,不言自明。

繼續閱讀