一狠裹、Nginx的模塊
Nginx由內(nèi)核和模塊組成病蛉,其中调违,內(nèi)核的設(shè)計(jì)非常微小和簡(jiǎn)潔窟哺,完成的工作也非常簡(jiǎn)單,僅僅通過(guò)查找配置文件將客戶端請(qǐng)求映射到一個(gè)location block(location是Nginx配置中的一個(gè)指令技肩,用于URL匹配)且轨,而在這個(gè)location中所配置的每個(gè)指令將會(huì)啟動(dòng)不同的模塊去完成相應(yīng)的工作。
Nginx的模塊從結(jié)構(gòu)上分為核心模塊虚婿、基礎(chǔ)模塊和第三方模塊:
- 核心模塊:HTTP模塊殖告、EVENT模塊和MAIL模塊
- 基礎(chǔ)模塊:HTTP Access模塊、HTTP FastCGI模塊雳锋、HTTP Proxy模塊和HTTP Rewrite模塊黄绩,
- 第三方模塊:HTTP Upstream Request Hash模塊、Notice模塊和HTTP Access Key模塊玷过。
Nginx的模塊從功能上分為如下三類爽丹。
- Handlers(處理器模塊)筑煮。此類模塊直接處理請(qǐng)求,并進(jìn)行輸出內(nèi)容和修改headers信息等操作粤蝎。Handlers處理器模塊一般只能有一個(gè)真仲。
- Filters (過(guò)濾器模塊)。此類模塊主要對(duì)其他處理器模塊輸出的內(nèi)容進(jìn)行修改操作初澎,最后由Nginx輸出秸应。
- Proxies (代理類模塊)。此類模塊是Nginx的HTTP Upstream之類的模塊碑宴,這些模塊主要與后端一些服務(wù)比如FastCGI等進(jìn)行交互软啼,實(shí)現(xiàn)服務(wù)代理和負(fù)載均衡等功能。
Nginx本身做的工作實(shí)際很少延柠,當(dāng)它接到一個(gè)HTTP請(qǐng)求時(shí)祸挪,它僅僅是通過(guò)查找配置文件將此次請(qǐng)求映射到一個(gè)location block,而此location中所配置的各個(gè)指令則會(huì)啟動(dòng)不同的模塊去完成工作贞间,因此模塊可以看做Nginx真正的勞動(dòng)工作者贿条。通常一個(gè)location中的指令會(huì)涉及一個(gè)handler模塊和多個(gè)filter模塊(當(dāng)然,多個(gè)location可以復(fù)用同一個(gè)模塊)增热。handler模塊負(fù)責(zé)處理請(qǐng)求整以,完成響應(yīng)內(nèi)容的生成,而filter模塊對(duì)響應(yīng)內(nèi)容進(jìn)行處理峻仇。
Nginx的模塊直接被編譯進(jìn)Nginx公黑,因此屬于靜態(tài)編譯方式。啟動(dòng)Nginx后础浮,Nginx的模塊被自動(dòng)加載,不像Apache奠骄,首先將模塊編譯為一個(gè)so文件豆同,然后在配置文件中指定是否進(jìn)行加載。在解析配置文件時(shí)含鳞,Nginx的每個(gè)模塊都有可能去處理某個(gè)請(qǐng)求影锈,但是同一個(gè)處理請(qǐng)求只能由一個(gè)模塊來(lái)完成。
二蝉绷、Nginx的多進(jìn)程IO模型
1. IO模型:blocking I/O
從圖宏觀來(lái)看鸭廷,左側(cè)為應(yīng)用程序,右側(cè)為內(nèi)核熔吗,當(dāng)應(yīng)用程序的進(jìn)程使用recvform函數(shù)發(fā)起對(duì)內(nèi)核的調(diào)用辆床,內(nèi)核開(kāi)始準(zhǔn)備數(shù)據(jù),一般來(lái)說(shuō)內(nèi)核需要收到一個(gè)完整的數(shù)據(jù)包(如UDP)桅狠,不會(huì)很快讼载,因此應(yīng)用程序的進(jìn)程處于阻塞等待的狀態(tài)轿秧,待內(nèi)核將數(shù)據(jù)準(zhǔn)備好,它將數(shù)據(jù)從內(nèi)核拷貝到用戶內(nèi)存咨堤,內(nèi)核才會(huì)返回結(jié)果菇篡,然后應(yīng)用程序解除阻塞狀態(tài),去處理下一步請(qǐng)求一喘,從本次過(guò)程驱还,做過(guò)開(kāi)發(fā)的基本都能理解,平時(shí)程序都是屬于這種阻塞的同步調(diào)用方式凸克。
2. IO模型:nonblocking I/O
從圖可以看出议蟆,應(yīng)用程序進(jìn)程當(dāng)使用recvform函數(shù)對(duì)內(nèi)核發(fā)起調(diào)用時(shí),內(nèi)核立即返回一個(gè)數(shù)據(jù)沒(méi)有準(zhǔn)備好的結(jié)果触徐,進(jìn)程通過(guò)輪詢不斷的去請(qǐng)求內(nèi)核咪鲜,詢問(wèn)數(shù)據(jù)是否給老子準(zhǔn)備好了,知道內(nèi)核返回結(jié)果撞鹉,說(shuō)已經(jīng)準(zhǔn)備好了疟丙,進(jìn)程才結(jié)束輪詢。
跟阻塞IO對(duì)比鸟雏,進(jìn)程本地不必阻塞等待享郊,而是隔三差五的通過(guò)輪詢調(diào)用,在這個(gè)過(guò)程中孝鹊,會(huì)大量的占用CPU的時(shí)間炊琉,所以一般Web服務(wù)器都不使用這種I/O模型。
3. IO模型:I/O multiplexing (select and poll)
多路復(fù)用模型新增了幾個(gè)函數(shù):select又活、poll苔咪、epoll(Linux2.6以后的內(nèi)核開(kāi)始支持),這幾個(gè)函數(shù)也會(huì)使進(jìn)程阻塞柳骄,但是和阻塞I/O所不同的团赏,這兩個(gè)函數(shù)可以同時(shí)阻塞多個(gè)I/O操作,而且可以同時(shí)對(duì)多個(gè)讀操作耐薯,多個(gè)寫(xiě)操作的I/O函數(shù)進(jìn)行監(jiān)測(cè)舔清,直到有數(shù)據(jù)可讀或可寫(xiě)時(shí),才真正調(diào)用I/O操作函數(shù)曲初,說(shuō)直白一點(diǎn)就是他們可以監(jiān)控多個(gè)內(nèi)核的IO操作体谒,一個(gè)頂仨,一個(gè)select會(huì)監(jiān)測(cè)多個(gè)socket臼婆,當(dāng)內(nèi)核準(zhǔn)備好其中一個(gè)數(shù)據(jù)時(shí)抒痒,select會(huì)立即通知進(jìn)行,趕快使用recvform調(diào)用內(nèi)核颁褂,讓內(nèi)核抓緊開(kāi)始拷貝數(shù)據(jù)到用戶內(nèi)存评汰,如此纷捞,它比阻塞IO好處就是一次能處理多個(gè)連接,而阻塞IO只能處理一個(gè)被去。
其中還有一個(gè)點(diǎn)主儡,就是epoll、poll要比select要高級(jí)一點(diǎn)惨缆,他們是無(wú)輪詢的糜值,因?yàn)樗麄冇胏allback,select需要通過(guò)遍歷Socket來(lái)完成調(diào)度坯墨,如果socket多寂汇,那肯定是需要浪費(fèi)CPU時(shí)間的,而epoll和poll使用回調(diào)函數(shù)捣染,給套接字注冊(cè)個(gè)回調(diào)函數(shù)骄瓣,當(dāng)他們活躍時(shí),自動(dòng)完成相關(guān)操作耍攘,就避免了輪詢榕栏,這些函數(shù)實(shí)際是阻塞進(jìn)程的。
4. IO模型:signal driven I/O (SIGIO)
信號(hào)驅(qū)動(dòng)IO蕾各,應(yīng)用程序進(jìn)程建立SIGIO處理函數(shù)調(diào)用內(nèi)核扒磁,內(nèi)核會(huì)立即返回?cái)?shù)據(jù)沒(méi)有準(zhǔn)備好的信號(hào),進(jìn)程不再阻塞式曲,待內(nèi)核準(zhǔn)備好后妨托,發(fā)送SIGIO信號(hào)給用戶進(jìn)程,然后用戶進(jìn)程通過(guò)阻塞的方式使用recvform函數(shù)調(diào)用內(nèi)核吝羞,讓內(nèi)核把數(shù)據(jù)拷貝到用戶內(nèi)存兰伤,并返回拷貝結(jié)果【牛看到此處是不是似曾相識(shí)敦腔,其實(shí)這有點(diǎn)回調(diào)的意思了。
5. IO模型:asynchronous I/O (the POSIX aio_functions)
異步IO卖氨,也就是AIO会烙,這個(gè)過(guò)程其實(shí)就非常簡(jiǎn)單负懦,應(yīng)用程序進(jìn)程調(diào)用內(nèi)核筒捺,內(nèi)核返回?cái)?shù)據(jù)沒(méi)有準(zhǔn)備好消息,進(jìn)程繼續(xù)去干別的事情纸厉,待內(nèi)核準(zhǔn)備好數(shù)據(jù)系吭,并且拷貝到用戶內(nèi)存,才通知進(jìn)程已完成數(shù)據(jù)拷貝颗品,因此肯尺,可以看出這種IO方式是效率最高的沃缘。
三、nginx的優(yōu)化
1. nginx.conf優(yōu)化
user nginx ;
pid /var/run/nginx.pid;
worker_processes auto; #定義了nginx對(duì)外提供web服務(wù)時(shí)的worder進(jìn)程數(shù)则吟。
worker_rlimit_nofile 100000; #worker進(jìn)程的最大打開(kāi)文件數(shù)限制
2. Events模塊
events {
worker_connections 2048; #設(shè)置可由一個(gè)worker進(jìn)程同時(shí)打開(kāi)的最大連接數(shù)
multi_accept on; #告訴nginx收到一個(gè)新連接通知后接受盡可能多的連接
use epoll; #用于復(fù)用客戶端線程的輪詢方法
}
3. HTTP 模塊
http {
server_tokens off; #關(guān)閉在錯(cuò)誤頁(yè)面中的nginx版本
sendfile on; #
tcp_nopush on; #告訴nginx在一個(gè)數(shù)據(jù)包里發(fā)送所有頭文件槐臀,而不一個(gè)接一個(gè)的發(fā)送
tcp_nodelay on; #告訴nginx不要緩存數(shù)據(jù),而是一段一段的發(fā)送
#當(dāng)需要及時(shí)發(fā)送數(shù)據(jù)時(shí)氓仲,就應(yīng)該給應(yīng)用設(shè)置這個(gè)屬性水慨,
#這樣發(fā)送一小塊數(shù)據(jù)信息時(shí)就不能立即得到返回值。
access_log off;
error_log /var/log/nginx/error.log crit;
...
}
timeout設(shè)置
keepalive_timeout 10; #給客戶端分配keep-alive鏈接超時(shí)時(shí)間敬扛。服務(wù)器將在這個(gè)超時(shí)時(shí)間過(guò)后關(guān)閉鏈接晰洒。
client_header_timeout 10; #設(shè)置請(qǐng)求頭
client_body_timeout 10; #和請(qǐng)求體(各自)的超時(shí)時(shí)間。我們也可以把這個(gè)設(shè)置低些啥箭。
reset_timedout_connection on;
#告訴nginx關(guān)閉不響應(yīng)的客戶端連接谍珊。這將會(huì)釋放那個(gè)客戶端所占有的內(nèi)存空間。
send_timeout 10; #在兩次客戶端讀取操作這段時(shí)間內(nèi)急侥,客戶端沒(méi)有讀取任何數(shù)據(jù)砌滞,nginx就會(huì)關(guān)閉連接。
連接限制
limit_conn_zone $binary_remote_addr zone=addr:5m;
#設(shè)置用于保存各種key(比如當(dāng)前連接數(shù))的共享內(nèi)存的參數(shù)
limit_conn addr 100; #我們?cè)试S每一個(gè)IP地址最多同時(shí)打開(kāi)有100個(gè)連接
type
include /etc/nginx/mime.types;
default_type text/html;
charset UTF-8;
gzip
gzip on; #采用gzip壓縮的形式發(fā)送數(shù)據(jù)
gzip_disable "msie6"; #為指定的客戶端禁用gzip功能
# gzip_static on;
gzip_proxied any; #允許或者禁止壓縮基于請(qǐng)求和響應(yīng)的響應(yīng)流缆巧。我們?cè)O(shè)置為any布持,意味著將會(huì)壓縮所有的請(qǐng)求
gzip_min_length 1000; #設(shè)置對(duì)數(shù)據(jù)啟用壓縮的最少字節(jié)數(shù)
gzip_comp_level 4; #設(shè)置數(shù)據(jù)的壓縮等級(jí)。這個(gè)等級(jí)可以是1-9之間的任意數(shù)值陕悬,9是最慢但是壓縮比最大的
gzip_types text/plain
text/css
application/json
application/x-javascript
text/xml
application/xml
application/xml+rss
text/javascript; #設(shè)置需要壓縮的數(shù)據(jù)格式
file_cache
open_file_cache max=100000 inactive=20s;
#打開(kāi)緩存的同時(shí)也指定了緩存最大數(shù)目题暖,以及緩存的時(shí)間。
#我們可以設(shè)置一個(gè)相對(duì)高的最大時(shí)間捉超,這樣我們可以在它們不活動(dòng)超過(guò)20秒后清除掉
open_file_cache_valid 30s; #在open_file_cache中指定檢測(cè)正確信息的間隔時(shí)間胧卤。
open_file_cache_min_uses 2; #定義了open_file_cache中指令參數(shù)不活動(dòng)時(shí)間期間里最小的文件數(shù)。
open_file_cache_errors on; #指定了當(dāng)搜索一個(gè)文件時(shí)是否緩存錯(cuò)誤信息
include /etc/nginx/conf.d/*.conf;
buffer
server_names_hash_bucket_size 128; #服務(wù)器名字的hash表大小
client_header_buffer_size 32k; #用于設(shè)置客戶端請(qǐng)求的Header頭緩沖區(qū)的大小拼岳,一般1kb就夠用
large_client_header_buffers 4 64k; #設(shè)置客戶端請(qǐng)求的Header頭緩沖區(qū)大小枝誊,默認(rèn)為4K∠е剑客戶端請(qǐng)求行不能超過(guò)設(shè)置的第一個(gè)數(shù)叶撒,請(qǐng)求的Header頭信息不能大于設(shè)置的第二個(gè)數(shù),否則會(huì)報(bào)"Request URI too large"(414)或“Bad request”(400)錯(cuò)誤耐版。如果客戶端的Cookie信息較大祠够,則需增加緩沖區(qū)大小
client_max_body_size 8m; #上傳文件大小限制
4. proxy_pass
proxy_buffering off;
proxy_buffer_size 128k;
proxy_buffers 100 128k;