Nginx原理

什么是Nginx嗅绰?

Nginx是一個高性能的HTTP和反向代理服務(wù)器匾寝,也是一個IMAP/POP3/SMTP服務(wù)器
Nginx是一款輕量級的Web服務(wù)器/反向代理服務(wù)器及電子郵件(IMAP/POP3)代理服務(wù)器

為什么要用Nginx掀虎?

優(yōu)點:

跨平臺叠艳、配置簡單
非阻塞鸠删、高并發(fā)連接:處理2-3萬并發(fā)連接數(shù)贫导,官方監(jiān)測能支持5萬并發(fā)
內(nèi)存消耗小:開啟10個nginx才占150M內(nèi)存
成本低廉:開源
內(nèi)置的健康檢查功能:如果有一個服務(wù)器宕機抛猫,會做一個健康檢查,再發(fā)送的請求就不會發(fā)送到宕機的服務(wù)器了孩灯。重新將請求提交到其他的節(jié)點上闺金。
節(jié)省寬帶:支持GZIP壓縮,可以添加瀏覽器本地緩存
穩(wěn)定性高:宕機的概率非常小
master/worker結(jié)構(gòu):一個master進程峰档,生成一個或者多個worker進程
接收用戶請求是異步的:瀏覽器將請求發(fā)送到nginx服務(wù)器败匹,它先將用戶請求全部接收下來匣距,再一次性發(fā)送給后端web服務(wù)器,極大減輕了web服務(wù)器的壓力
一邊接收web服務(wù)器的返回數(shù)據(jù)哎壳,一邊發(fā)送給瀏覽器客戶端
網(wǎng)絡(luò)依賴性比較低毅待,只要ping通就可以負載均衡
可以有多臺nginx服務(wù)器
事件驅(qū)動:通信機制采用epoll模型

Nginx是如何處理一個請求的呢?

首先归榕,nginx在啟動時尸红,會解析配置文件,得到需要監(jiān)聽的端口與ip地址刹泄,然后在nginx的master進程里面
先初始化好這個監(jiān)控的socket(創(chuàng)建socket外里,設(shè)置addrreuse等選項,綁定到指定的ip地址端口特石,再listen)
然后再fork(一個現(xiàn)有進程可以調(diào)用fork函數(shù)創(chuàng)建一個新進程盅蝗。由fork創(chuàng)建的新進程被稱為子進程 )出多個子進程出來
然后子進程會競爭accept新的連接。此時姆蘸,客戶端就可以向nginx發(fā)起連接了墩莫。當客戶端與nginx進行三次握手,與nginx建立好一個連接后
此時逞敷,某一個子進程會accept成功狂秦,得到這個建立好的連接的socket,然后創(chuàng)建nginx對連接的封裝推捐,即ngx_connection_t結(jié)構(gòu)體
接著裂问,設(shè)置讀寫事件處理函數(shù)并添加讀寫事件來與客戶端進行數(shù)據(jù)的交換。最后牛柒,nginx或客戶端來主動關(guān)掉連接堪簿,到此,一個連接就壽終正寢了

Nginx處理Http請求的過程

表面上看皮壁,當Nginx處理一個來自客戶端的請求時椭更,先根據(jù)請求頭的host、ip和port來確定由哪個server處理闪彼,
確定了server之后甜孤,再根據(jù)請求的uri找到對應(yīng)的location,這個請求就由這個location處理畏腕。
實際Nginx將一個請求的處理劃分為若干個不同階段(phase)缴川,這些階段按照前后順序依次執(zhí)行,也就是說NGX_HTTP_POST_READ_PHASE在第一個描馅,NGX_HTTP_LOG_PHASE在最后一個把夸。

進程模塊

Nginx 默認采用守護模式啟動,守護模式讓master進程啟動后在后臺運行铭污,不在窗口上卡住恋日。
Nginx 啟動后會有一個 Master 進程和多個Worker 進程膀篮,Master 進程主要用來管理 Worker 進程,對網(wǎng)絡(luò)事件進程進行收集和分發(fā)岂膳,調(diào)度哪個模塊可以占用 CPU 資源誓竿,從而處理請求。一般配置Worker進程的個數(shù)與機器cpu個數(shù)一致谈截,從而打到cpu資源的最大化利用筷屡,也避免由于進程資源分配帶來的額外開銷。

Master進程工作原理

  • Master 進程的工作包括
  • 接收來自外界的信號
  • 向各worker進程發(fā)送信號
  • 監(jiān)控worker進程的運行狀態(tài)簸喂,當worker進程退出后(異常情況下)毙死,會自動重新啟動新的worker進程

驚群現(xiàn)象

驚群現(xiàn)象:當listen_fd有新的accept()請求過來,操作系統(tǒng)會喚醒所有子進程,因為這些進程都epoll_wait()同一個listen_fd,操作系統(tǒng)又無從判斷由誰來負責accept,索性干脆全部叫醒,但最終只會有一個進程成功accept,其他進程accept失敗.所有子進程都是被"嚇醒"的,所以稱之為Thundering Herd(驚群).

Nginx解決驚群的思路:避免驚群.
使用全局互斥鎖(accept_mutex on),每個工作進程在epoll_wait()之前先去申請鎖,申請到則繼續(xù)處理,獲取不到則等待,并設(shè)置了一個負載均衡的算法(當某一個工作進程的任務(wù)量達到總設(shè)置量的7/8時,則不會再嘗試去申請鎖)來均衡各個進程的任務(wù)量.

Worker進程工作原理

當一個worker進程在accept這個連接之后,就開始讀取請求喻鳄,解析請求扼倘,處理請求,產(chǎn)生數(shù)據(jù)后除呵,再返回給客戶端再菊,最后才斷開連接,這樣一個完整的請求就是這樣的了竿奏。我們可以看到袄简,一個請求,完全由worker進程來處理泛啸,而且只在一個worker進程中處理。

采用這種方式的好處:

  • 節(jié)省鎖帶來的開銷秃症。對于每個worker進程來說候址,獨立的進程,不需要加鎖种柑,所以省掉了鎖帶來的開銷岗仑,同時在編程以及問題查上時,也會方便很多
  • 獨立進程聚请,減少風險荠雕。采用獨立的進程,可以讓互相之間不會影響驶赏,一個進程退出后炸卑,其它進程還在工作,服務(wù)不會中斷煤傍,master進程則很快重新啟動新的worker進程
  • 在一次請求里無需進程切換

事件模塊

一個請求的基本過程:建立連接 - 接受連接 - 發(fā)送數(shù)據(jù)盖文,在系統(tǒng)底層就是讀寫事件。

Epoll 模型

Epoll出現(xiàn)在 linux2.6以后蚯姆,Nginx采用 Epoll 這種異步非阻塞的事件處理機制五续。這種機制的原理就是把一個完整的請求洒敏,劃分成多個事件,比如accept()疙驾, recv()凶伙,磁盤I/O,send()它碎,每個事件都有不同的模塊進行處理函荣。一個請求由一個worker進程處理,在請求多的時候链韭,無需頻繁的切換進程偏竟。

  • master進程先建好需要listen的socket后,然后再fork出多個woker進程敞峭,這樣每個work進程都可以去accept這個socket
  • 當一個client連接到來時踊谋,所有accept的work進程都會受到通知,但只有一個進程可以accept成功旋讹,其它的則會accept失敗殖蚕,Nginx提供了一把共享鎖accept_mutex來保證同一時刻只有一個work進程在accept連接,從而解決驚群問題
  • 當一個worker進程accept這個連接后沉迹,就開始讀取請求睦疫,解析請求,處理請求鞭呕,產(chǎn)生數(shù)據(jù)后蛤育,再返回給客戶端,最后才斷開連接葫松,這樣一個完成的請求就結(jié)束了

Epoll 是基于一個進程處理多個連接瓦糕、非阻塞IO的策略,Nginx多使用這種策略腋么。

Select 模型

Select 模型在啟動的時候創(chuàng)建多個進程咕娄,放在一個進程池里,并且進程池里的進程數(shù)會隨著請求數(shù)目的增加而增加珊擂,對于每一個連接圣勒,都是在一個進程內(nèi)處理完畢。所以Select模型能接收的并發(fā)量受到所能開啟的進程數(shù)影響摧扇,進程之間是互相阻塞的圣贸,且頻繁的切換進程造成大量開銷。

Select 是基于一個線程處理一個請求的非阻塞IO的策略扳剿,Apache使用這種策略旁趟。

網(wǎng)絡(luò)模塊

最大連接數(shù)

當作為http服務(wù)器的時候:max_clients = worker_processes * worker_connections;
當作為反向代理的時候:max_clients = worker_processes * worker_connections/4

負載均衡

nginx的upstream目前支持的5種方式的分配:

  • 輪詢(默認)
    每個請求按時間順序逐一分配到不同的后端服務(wù)器,如果后端服務(wù)器down掉,能自動剔除锡搜。
    upstream backserver {
    server host:port;
    server host:port;
    }
  • weight
    指定輪詢幾率橙困,weight和訪問比率成正比,用于后端服務(wù)器性能不均的情況

upstream backserver {
server host:port weight=10;
server host:port weight=10;
}

  • ip_hash
    每個請求按訪問ip的hash結(jié)果分配耕餐,這樣每個訪客固定訪問一個后端服務(wù)器凡傅,可以解決session的問題
    upstream backserver {
    ip_hash;
    server host:port;
    server host:port;
    }
  • fair(第三方)
    按后端服務(wù)器的響應(yīng)時間來分配請求,響應(yīng)時間短的優(yōu)先分配肠缔。

upstream backserver {
server server1;
server server2;
fair;
}

  • url_hash(第三方)
    按訪問url的hash結(jié)果來分配請求夏跷,使每個url定向到同一個后端服務(wù)器,后端服務(wù)器為緩存時比較有效

upstream backserver {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}

代理緩存

# 代理緩沖區(qū)相關(guān)配置
    proxy_buffer_size   128k;
    proxy_buffers   4 256k;
    proxy_busy_buffers_size   256k;

    # 通過令牌桶原理實現(xiàn)用戶訪問次數(shù)限制
    limit_req_zone  $http_x_forwarded_for zone=req_one:10m rate=30r/s;

    #設(shè)置Web緩存區(qū)名稱為cache_web明未,內(nèi)存緩存空間大小為300MB槽华,1天沒有被訪問的內(nèi)容自動清除,硬盤緩存空間
    #大小為3GB趟妥。
    proxy_temp_path   /xxx/proxy_temp_dir 1 2;
    proxy_cache_path  /xxx/proxy_cache_dir levels=1:2 keys_zone=cache_web:300m inactive=1d max_size=1g;

訪問控制

location ~ /.ht {
deny all;
}

負載均衡用法

1猫态、后端服務(wù)器

通過 upstream 可以設(shè)定后端服務(wù)器,指定的方式可以是 IP 地址與端口披摄、域名亲雪、UNIX 套接字(socket)。其中如果域名可以被解析為多個地址疚膊,則這些地址都作為 backend义辕。下面舉例說明:

upstream backend {
    server blog.csdn.net/poechant;
    server 145.223.156.89:8090;
    server unix:/tmp/backend3;
}

2、負載均衡策略

分為輪詢(round robin)寓盗、用戶 IP 哈希(client IP)和指定權(quán)重 3 種方式灌砖,默認情況下,提供輪詢作為負載均衡策略傀蚌。

3周崭、重試策略

可以為每個 backend 指定最大的重試次數(shù),和重試時間間隔喳张。所使用的關(guān)鍵字是 max_fails 和 fail_timeout。如下所示:
upstream backend {
server backend1.example.com weight=5;
server 54.244.56.3:8081 max_fails=3 fail_timeout=30s;
}

4美澳、備機策略

可以使用“backup”關(guān)鍵字销部。當所有的非備機(non-backup)都宕機(down)或者繁忙(busy)的時候,就只使用由 backup 標注的備機制跟。必須要注意的是舅桩,backup 不能和 ip_hash 關(guān)鍵字一起使用。舉例如下:
upstream backend {
server backend1.example.com;
server backend2.example.com backup;
server backend3.example.com;
}

相關(guān)配置

######Nginx配置文件nginx.conf中文詳解#####

#定義Nginx運行的用戶和用戶組
user www www;

#nginx進程數(shù)雨膨,建議設(shè)置為等于CPU總核心數(shù)擂涛。
worker_processes 8;
 
#全局錯誤日志定義類型,[ debug | info | notice | warn | error | crit ]
error_log /usr/local/nginx/logs/error.log info;

#進程pid文件
pid /usr/local/nginx/logs/nginx.pid;

#指定進程可以打開的最大描述符:數(shù)目
#工作模式與連接數(shù)上限
#這個指令是指當一個nginx進程打開的最多文件描述符數(shù)目聊记,理論值應(yīng)該是最多打開文件數(shù)(ulimit -n)與nginx進程數(shù)相除撒妈,但是nginx分配請求并不是那么均勻恢暖,所以最好與ulimit -n 的值保持一致。
#現(xiàn)在在linux 2.6內(nèi)核下開啟文件打開數(shù)為65535狰右,worker_rlimit_nofile就相應(yīng)應(yīng)該填寫65535杰捂。
#這是因為nginx調(diào)度時分配請求到進程并不是那么的均衡,所以假如填寫10240棋蚌,總并發(fā)量達到3-4萬時就有進程可能超過10240了嫁佳,這時會返回502錯誤。
worker_rlimit_nofile 65535;


events
{
    #參考事件模型谷暮,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型
    #是Linux 2.6以上版本內(nèi)核中的高性能網(wǎng)絡(luò)I/O模型蒿往,linux建議epoll,如果跑在FreeBSD上面湿弦,就用kqueue模型瓤漏。
    #補充說明:
    #與apache相類,nginx針對不同的操作系統(tǒng)省撑,有不同的事件模型
    #A)標準事件模型
    #Select赌蔑、poll屬于標準事件模型,如果當前系統(tǒng)不存在更有效的方法竟秫,nginx會選擇select或poll
    #B)高效事件模型
    #Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用雙處理器的MacOS X系統(tǒng)使用kqueue可能會造成內(nèi)核崩潰娃惯。
    #Epoll:使用于Linux內(nèi)核2.6版本及以后的系統(tǒng)。
    #/dev/poll:使用于Solaris 7 11/99+肥败,HP/UX 11.22+ (eventport)趾浅,IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
    #Eventport:使用于Solaris 10馒稍。 為了防止出現(xiàn)內(nèi)核崩潰的問題皿哨, 有必要安裝安全補丁。
    use epoll;

    #單個進程最大連接數(shù)(最大連接數(shù)=連接數(shù)*進程數(shù))
    #根據(jù)硬件調(diào)整纽谒,和前面工作進程配合起來用证膨,盡量大,但是別把cpu跑到100%就行鼓黔。每個進程允許的最多連接數(shù)央勒,理論上每臺nginx服務(wù)器的最大連接數(shù)為。
    worker_connections 65535;

    #keepalive超時時間澳化。
    keepalive_timeout 60;

    #客戶端請求頭部的緩沖區(qū)大小崔步。這個可以根據(jù)你的系統(tǒng)分頁大小來設(shè)置,一般一個請求頭的大小不會超過1k缎谷,不過由于一般系統(tǒng)分頁都要大于1k井濒,所以這里設(shè)置為分頁大小。
    #分頁大小可以用命令getconf PAGESIZE 取得。
    #[root@web001 ~]# getconf PAGESIZE
    #4096
    #但也有client_header_buffer_size超過4k的情況瑞你,但是client_header_buffer_size該值必須設(shè)置為“系統(tǒng)分頁大小”的整倍數(shù)酪惭。
    client_header_buffer_size 4k;

    #這個將為打開文件指定緩存,默認是沒有啟用的捏悬,max指定緩存數(shù)量撞蚕,建議和打開文件數(shù)一致,inactive是指經(jīng)過多長時間文件沒被請求后刪除緩存过牙。
    open_file_cache max=65535 inactive=60s;

    #這個是指多長時間檢查一次緩存的有效信息甥厦。
    #語法:open_file_cache_valid time 默認值:open_file_cache_valid 60 使用字段:http, server, location 這個指令指定了何時需要檢查open_file_cache中緩存項目的有效信息.
    open_file_cache_valid 80s;

    #open_file_cache指令中的inactive參數(shù)時間內(nèi)文件的最少使用次數(shù),如果超過這個數(shù)字寇钉,文件描述符一直是在緩存中打開的刀疙,如上例,如果有一個文件在inactive時間內(nèi)一次沒被使用扫倡,它將被移除谦秧。
    #語法:open_file_cache_min_uses number 默認值:open_file_cache_min_uses 1 使用字段:http, server, location  這個指令指定了在open_file_cache指令無效的參數(shù)中一定的時間范圍內(nèi)可以使用的最小文件數(shù),如果使用更大的值,文件描述符在cache中總是打開狀態(tài).
    open_file_cache_min_uses 1;
    
    #語法:open_file_cache_errors on | off 默認值:open_file_cache_errors off 使用字段:http, server, location 這個指令指定是否在搜索一個文件是記錄cache錯誤.
    open_file_cache_errors on;
}
 
 
 
#設(shè)定http服務(wù)器,利用它的反向代理功能提供負載均衡支持
http
{
    #文件擴展名與文件類型映射表
    include mime.types;

    #默認文件類型
    default_type application/octet-stream;

    #默認編碼
    #charset utf-8;

    #服務(wù)器名字的hash表大小
    #保存服務(wù)器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的撵溃。參數(shù)hash bucket size總是等于hash表的大小疚鲤,并且是一路處理器緩存大小的倍數(shù)。在減少了在內(nèi)存中的存取次數(shù)后缘挑,使在處理器中加速查找hash表鍵值成為可能集歇。如果hash bucket size等于一路處理器緩存的大小,那么在查找鍵的時候语淘,最壞的情況下在內(nèi)存中查找的次數(shù)為2诲宇。第一次是確定存儲單元的地址,第二次是在存儲單元中查找鍵 值惶翻。因此姑蓝,如果Nginx給出需要增大hash max size 或 hash bucket size的提示,那么首要的是增大前一個參數(shù)的大小.
    server_names_hash_bucket_size 128;

    #客戶端請求頭部的緩沖區(qū)大小吕粗。這個可以根據(jù)你的系統(tǒng)分頁大小來設(shè)置纺荧,一般一個請求的頭部大小不會超過1k,不過由于一般系統(tǒng)分頁都要大于1k颅筋,所以這里設(shè)置為分頁大小虐秋。分頁大小可以用命令getconf PAGESIZE取得。
    client_header_buffer_size 32k;

    #客戶請求頭緩沖大小垃沦。nginx默認會用client_header_buffer_size這個buffer來讀取header值,如果header過大用押,它會使用large_client_header_buffers來讀取肢簿。
    large_client_header_buffers 4 64k;

    #設(shè)定通過nginx上傳文件的大小
    client_max_body_size 8m;

    #開啟高效文件傳輸模式,sendfile指令指定nginx是否調(diào)用sendfile函數(shù)來輸出文件,對于普通應(yīng)用設(shè)為 on池充,如果用來進行下載等應(yīng)用磁盤IO重負載應(yīng)用桩引,可設(shè)置為off,以平衡磁盤與網(wǎng)絡(luò)I/O處理速度收夸,降低系統(tǒng)的負載坑匠。注意:如果圖片顯示不正常把這個改成off。
    #sendfile指令指定 nginx 是否調(diào)用sendfile 函數(shù)(zero copy 方式)來輸出文件卧惜,對于普通應(yīng)用厘灼,必須設(shè)為on。如果用來進行下載等應(yīng)用磁盤IO重負載應(yīng)用咽瓷,可設(shè)置為off设凹,以平衡磁盤與網(wǎng)絡(luò)IO處理速度,降低系統(tǒng)uptime茅姜。
    sendfile on;

    #開啟目錄列表訪問闪朱,合適下載服務(wù)器,默認關(guān)閉钻洒。
    autoindex on;

    #此選項允許或禁止使用socke的TCP_CORK的選項奋姿,此選項僅在使用sendfile的時候使用
    tcp_nopush on;
     
    tcp_nodelay on;

    #長連接超時時間埠忘,單位是秒
    keepalive_timeout 120;

    #FastCGI相關(guān)參數(shù)是為了改善網(wǎng)站的性能:減少資源占用颠通,提高訪問速度。下面參數(shù)看字面意思都能理解渐白。
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 128k;

    #gzip模塊設(shè)置
    gzip on; #開啟gzip壓縮輸出
    gzip_min_length 1k;    #最小壓縮文件大小
    gzip_buffers 4 16k;    #壓縮緩沖區(qū)
    gzip_http_version 1.0;    #壓縮版本(默認1.1糯钙,前端如果是squid2.5請使用1.0)
    gzip_comp_level 2;    #壓縮等級
    gzip_types text/plain application/x-javascript text/css application/xml;    #壓縮類型粪狼,默認就已經(jīng)包含textml,所以下面就不用再寫了任岸,寫上去也不會有問題再榄,但是會有一個warn。
    gzip_vary on;

    #開啟限制IP連接數(shù)的時候需要使用
    #limit_zone crawler $binary_remote_addr 10m;



    #負載均衡配置 可設(shè)置多個upstream享潜,每個upstream為一組
    upstream piao.jd.com {
     
        #upstream的負載均衡困鸥,weight是權(quán)重,可以根據(jù)機器配置定義權(quán)重剑按。weigth參數(shù)表示權(quán)值疾就,權(quán)值越高被分配到的幾率越大。
        server 192.168.80.121:80 weight=3;
        server 192.168.80.122:80 weight=2;
        server 192.168.80.123:80 weight=3;

        #nginx的upstream目前支持4種方式的分配
        #1艺蝴、輪詢(默認)
        #每個請求按時間順序逐一分配到不同的后端服務(wù)器猬腰,如果后端服務(wù)器down掉,能自動剔除猜敢。
        #2姑荷、weight
        #指定輪詢幾率盒延,weight和訪問比率成正比,用于后端服務(wù)器性能不均的情況鼠冕。
        #例如:
        #upstream bakend {
        #    server 192.168.0.14 weight=10;
        #    server 192.168.0.15 weight=10;
        #}
        #2添寺、ip_hash
        #每個請求按訪問ip的hash結(jié)果分配,這樣每個訪客固定訪問一個后端服務(wù)器懈费,可以解決session的問題计露。
        #例如:
        #upstream bakend {
        #    ip_hash;
        #    server 192.168.0.14:88;
        #    server 192.168.0.15:80;
        #}
        #3、fair(第三方)
        #按后端服務(wù)器的響應(yīng)時間來分配請求憎乙,響應(yīng)時間短的優(yōu)先分配票罐。
        #upstream backend {
        #    server server1;
        #    server server2;
        #    fair;
        #}
        #4、url_hash(第三方)
        #按訪問url的hash結(jié)果來分配請求寨闹,使每個url定向到同一個后端服務(wù)器胶坠,后端服務(wù)器為緩存時比較有效。
        #例:在upstream中加入hash語句繁堡,server語句中不能寫入weight等其他的參數(shù)沈善,hash_method是使用的hash算法
        #upstream backend {
        #    server squid1:3128;
        #    server squid2:3128;
        #    hash $request_uri;
        #    hash_method crc32;
        #}

        #tips:
        #upstream bakend{#定義負載均衡設(shè)備的Ip及設(shè)備狀態(tài)}{
        #    ip_hash;
        #    server 127.0.0.1:9090 down;
        #    server 127.0.0.1:8080 weight=2;
        #    server 127.0.0.1:6060;
        #    server 127.0.0.1:7070 backup;
        #}
        #在需要使用負載均衡的server中增加 proxy_pass http://bakend/;

        #每個設(shè)備的狀態(tài)設(shè)置為:
        #1.down表示單前的server暫時不參與負載
        #2.weight為weight越大,負載的權(quán)重就越大椭蹄。
        #3.max_fails:允許請求失敗的次數(shù)默認為1.當超過最大次數(shù)時闻牡,返回proxy_next_upstream模塊定義的錯誤
        #4.fail_timeout:max_fails次失敗后,暫停的時間绳矩。
        #5.backup: 其它所有的非backup機器down或者忙的時候罩润,請求backup機器。所以這臺機器壓力會最輕翼馆。

        #nginx支持同時設(shè)置多組的負載均衡割以,用來給不用的server來使用。
        #client_body_in_file_only設(shè)置為On 可以講client post過來的數(shù)據(jù)記錄到文件中用來做debug
        #client_body_temp_path設(shè)置記錄文件的目錄 可以設(shè)置最多3層目錄
        #location對URL進行匹配.可以進行重定向或者進行新的代理 負載均衡
    }
     
     
     
    #虛擬主機的配置 可設(shè)置多個Server应媚,做多個站點
    server
    {
        #監(jiān)聽端口
        listen 80;

        #域名可以有多個严沥,用空格隔開
        server_name www.jd.com jd.com;
        index index.html index.htm index.php;
        root /data/www/jd;

        #對******進行負載均衡
        location ~ .*.(php|php5)?$
        {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            include fastcgi.conf;
        }
         
        #圖片緩存時間設(shè)置
        location ~ .*.(gif|jpg|jpeg|png|bmp|swf)$
        {
            expires 10d;
        }
         
        #JS和CSS緩存時間設(shè)置
        location ~ .*.(js|css)?$
        {
            expires 1h;
        }
         
        #日志格式設(shè)定
        #$remote_addr與$http_x_forwarded_for用以記錄客戶端的ip地址;
        #$remote_user:用來記錄客戶端用戶名稱中姜;
        #$time_local: 用來記錄訪問時間與時區(qū)消玄;
        #$request: 用來記錄請求的url與http協(xié)議;
        #$status: 用來記錄請求狀態(tài)丢胚;成功是200翩瓜,
        #$body_bytes_sent :記錄發(fā)送給客戶端文件主體內(nèi)容大小携龟;
        #$http_referer:用來記錄從那個頁面鏈接訪問過來的兔跌;
        #$http_user_agent:記錄客戶瀏覽器的相關(guān)信息;
        #通常web服務(wù)器放在反向代理的后面峡蟋,這樣就不能獲取到客戶的IP地址了浮定,通過$remote_add拿到的IP地址是反向代理服務(wù)器的iP地址相满。反向代理服務(wù)器在轉(zhuǎn)發(fā)請求的http頭信息中,可以增加x_forwarded_for信息桦卒,用以記錄原有客戶端的IP地址和原來客戶端的請求的服務(wù)器地址。
        log_format access '$remote_addr - $remote_user [$time_local] "$request" '
        '$status $body_bytes_sent "$http_referer" '
        '"$http_user_agent" $http_x_forwarded_for';
         
        #定義本虛擬主機的訪問日志
        access_log  /usr/local/nginx/logs/host.access.log  main;
        access_log  /usr/local/nginx/logs/host.access.404.log  log404;
         
        #對 "/" 啟用反向代理  ----server_name下轉(zhuǎn)發(fā)到后端服務(wù)器地址配置
        location / {
            #轉(zhuǎn)發(fā)到后端服務(wù)器地址配置匿又,要做負載方灾,配置upstream的名稱即可
            proxy_pass http://upstream_name;
             #用來定義故障轉(zhuǎn)移策略,當后端服務(wù)節(jié)點返回 500碌更、 502裕偿、 503、504 和執(zhí)行超時等錯誤時痛单,自動將請求轉(zhuǎn)發(fā)到upstream負載均衡組中的另一臺服務(wù)器嘿棘,實現(xiàn)故障轉(zhuǎn)移。
            proxy_next_upstream http_500 http_502 http_503 error timeout invalid_header;
            ##禁止重定向
            proxy_redirect off;
            #proxy_set_header設(shè)置由后端的服務(wù)器獲取用戶的主機名或真實IP地址旭绒,以及代理者的真實IP地址鸟妙。
            proxy_set_header X-Real-IP $remote_addr;
            #后端的Web服務(wù)器可以通過X-Forwarded-For獲取用戶真實IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #以下是一些反向代理的配置,可選挥吵。
            proxy_set_header Host $host;

            #允許客戶端請求的最大單文件字節(jié)數(shù)
            client_max_body_size 10m;

            #緩沖區(qū)代理緩沖用戶端請求的最大字節(jié)數(shù)重父,
            #如果把它設(shè)置為比較大的數(shù)值,例如256k忽匈,那么房午,無論使用firefox還是IE瀏覽器,來提交任意小于256k的圖片丹允,都很正常郭厌。如果注釋該指令,使用默認的client_body_buffer_size設(shè)置雕蔽,也就是操作系統(tǒng)頁面大小的兩倍折柠,8k或者16k,問題就出現(xiàn)了萎羔。
            #無論使用firefox4.0還是IE8.0液走,提交一個比較大,200k左右的圖片贾陷,都返回500 Internal Server Error錯誤
            client_body_buffer_size 128k;

            #表示使nginx阻止HTTP應(yīng)答代碼為400或者更高的應(yīng)答缘眶。
            proxy_intercept_errors on;

            #后端服務(wù)器連接的超時時間_發(fā)起握手等候響應(yīng)超時時間
            #nginx跟后端服務(wù)器連接超時時間(代理連接超時)
            proxy_connect_timeout 90;

            #后端服務(wù)器數(shù)據(jù)回傳時間(代理發(fā)送超時)
            #后端服務(wù)器數(shù)據(jù)回傳時間_就是在規(guī)定時間之內(nèi)后端服務(wù)器必須傳完所有的數(shù)據(jù)
            proxy_send_timeout 90;

            #連接成功后,后端服務(wù)器響應(yīng)時間(代理接收超時)
            #連接成功后_等候后端服務(wù)器響應(yīng)時間_其實已經(jīng)進入后端的排隊之中等候處理(也可以說是后端服務(wù)器處理請求的時間)
            proxy_read_timeout 90;

            #設(shè)置代理服務(wù)器(nginx)保存用戶頭信息的緩沖區(qū)大小
            #設(shè)置從被代理服務(wù)器讀取的第一部分應(yīng)答的緩沖區(qū)大小髓废,通常情況下這部分應(yīng)答中包含一個小的應(yīng)答頭巷懈,默認情況下這個值的大小為指令proxy_buffers中指定的一個緩沖區(qū)的大小,不過可以將其設(shè)置為更小
            proxy_buffer_size 4k;

            #proxy_buffers緩沖區(qū)慌洪,網(wǎng)頁平均在32k以下的設(shè)置
            #設(shè)置用于讀取應(yīng)答(來自被代理服務(wù)器)的緩沖區(qū)數(shù)目和大小顶燕,默認情況也為分頁大小凑保,根據(jù)操作系統(tǒng)的不同可能是4k或者8k
            proxy_buffers 4 32k;

            #高負荷下緩沖大小(proxy_buffers*2)
            proxy_busy_buffers_size 64k;

            #設(shè)置在寫入proxy_temp_path時數(shù)據(jù)的大小涌攻,預(yù)防一個工作進程在傳遞文件時阻塞太長
            #設(shè)定緩存文件夾大小欧引,大于這個值,將從upstream服務(wù)器傳
            proxy_temp_file_write_size 64k;
        }
         
         
        #設(shè)定查看Nginx狀態(tài)的地址
        location /NginxStatus {
            stub_status on;
            access_log on;
            auth_basic "NginxStatus";
            auth_basic_user_file confpasswd;
            #htpasswd文件的內(nèi)容可以用apache提供的htpasswd工具來產(chǎn)生恳谎。
        }
         
        #本地動靜分離反向代理配置
        #所有jsp的頁面均交由tomcat或resin處理
        location ~ .(jsp|jspx|do)?$ {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:8080;
        }
         
        #所有靜態(tài)文件由nginx直接讀取不經(jīng)過tomcat或resin
        location ~ .*.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|
        pdf|xls|mp3|wma)$
        {
            expires 15d; 
        }
         
        location ~ .*.(js|css)?$
        {
            expires 1h;
        }
    }
}
######Nginx配置文件nginx.conf中文詳解#####

Nginx的模塊與工作原理

Nginx由內(nèi)核和模塊組成芝此,其中,內(nèi)核的設(shè)計非常微小和簡潔因痛,完成的工作也非常簡單婚苹,僅僅通過查找配置文件將客戶端請求映射到一個location block(location是Nginx配置中的一個指令,用于URL匹配)鸵膏,而在這個location中所配置的每個指令將會啟動不同的模塊去完成相應(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模塊。

用戶根據(jù)自己的需要開發(fā)的模塊都屬于第三方模塊攀操。正是有了這么多模塊的支撐院仿,Nginx的功能才會如此強大。

Nginx的模塊從功能上分為如下三類速和。

Handlers(處理器模塊)歹垫。此類模塊直接處理請求,并進行輸出內(nèi)容和修改headers信息等操作颠放。Handlers處理器模塊一般只能有一個排惨。

Filters (過濾器模塊)。此類模塊主要對其他處理器模塊輸出的內(nèi)容進行修改操作碰凶,最后由Nginx輸出暮芭。

Proxies (代理類模塊)。此類模塊是Nginx的HTTP Upstream之類的模塊欲低,這些模塊主要與后端一些服務(wù)比如FastCGI等進行交互辕宏,實現(xiàn)服務(wù)代理和負載均衡等功能。


Nginx本身做的工作實際很少砾莱,當它接到一個HTTP請求時瑞筐,它僅僅是通過查找配置文件將此次請求映射到一個location block,而此location中所配置的各個指令則會啟動不同的模塊去完成工作腊瑟,因此模塊可以看做Nginx真正的勞動工作者聚假。通常一個location中的指令會涉及一個handler模塊和多個filter模塊(當然块蚌,多個location可以復(fù)用同一個模塊)。handler模塊負責處理請求膘格,完成響應(yīng)內(nèi)容的生成峭范,而filter模塊對響應(yīng)內(nèi)容進行處理。

Nginx的模塊直接被編譯進Nginx瘪贱,因此屬于靜態(tài)編譯方式虎敦。啟動Nginx后,Nginx的模塊被自動加載政敢,不像Apache,首先將模塊編譯為一個so文件胚迫,然后在配置文件中指定是否進行加載喷户。在解析配置文件時,Nginx的每個模塊都有可能去處理某個請求访锻,但是同一個處理請求只能由一個模塊來完成褪尝。

Nginx中的進程間通信

我們知道,Linux提供了多種進程間傳遞消息的方式,比如共享內(nèi)存期犬、套接字河哑、管道、消息隊列龟虎、信號等璃谨,每種方式都各有特點,各有優(yōu)缺點鲤妥。其中Nginx主要使用了其中的三種方式:

  • 套接字(匿名套接字對)
  • 共享內(nèi)存
  • 信號
    本文主要結(jié)合代碼講一下前兩種方式佳吞,匿名套接字對和共享內(nèi)存在Nginx中的使用。

Nginx中的channel通信機制

概述

Nginx中的channel通信棉安,本質(zhì)上是多個進程之間,利用匿名套接字(socketpair)對來進行通信底扳。
我們知道,socketpair可以創(chuàng)建出一對套接字,在這兩個套接字的任何一個上面進行寫操作,在另一個套接字上就可以相應(yīng)的進行讀操作,而且這個管道是全雙工的。
那么,當父進程在調(diào)用了socketpair創(chuàng)建出一對匿名套接字對(A1,B1)后,fork出一個子進程,那么此時子進程也繼承了這一對套接字對(A2,B2)贡耽。在這個基礎(chǔ)上,父子進程即可進行通信了衷模。例如,父進程對A1進行寫操作,子進程可通過B2進行相應(yīng)的讀操作;子進程對B2進行寫操作,父進程可以通過A1來進行相應(yīng)的讀操作等等。
我們假設(shè),父進程依次fork了N個子進程,在每次fork之前,均如前所述調(diào)用了socketpair建立起一個匿名套接字對,這樣,父進程與各個子進程之間即可通過各自的套接字對來進行通信蒲赂。
但是各子進程之間能否使用匿名套接字對來進行通信呢阱冶?
我們假設(shè)父進程A中,它與子進程B之間的匿名套接字對為AB[2],它與子進程C之間的匿名套接字對為AC[2]。且進程B在進程C之前被fork出來凳宙。
對進程B而言熙揍,當它被fork出來后,它就繼承了父進程創(chuàng)建的套接字對,命名為BA[2],這樣父進程通過操作AB[2]氏涩,子進程B通過操作BA[2],即可實現(xiàn)父子進程之間的通信届囚。
對進程C而言,當它被fork出來后有梆,他就繼承了父進程穿件的套接字對,命名為CA[2],這樣父進程通過操作AC[2]意系,子進程C通過操作CA[2]泥耀,即可實現(xiàn)父子進程之間的通信。
但B和C有一點不同蛔添。由于B進程在C之前被fork痰催,B進程無法從父進程中繼承到父進程與C進程之間的匿名套接字對,而C進程在后面被fork出來,它卻從父進程處繼承到了父進程與子進程B之間的匿名套接字對迎瞧。
這樣夸溶,之后被fork出來的進程C,可以通過它從父進程那里繼承到的與B進程相關(guān)聯(lián)的匿名套接字對來向進程B發(fā)送消息,但進程B卻無法向進程C發(fā)送消息凶硅。
當子進程數(shù)量比較多時缝裁,就會造成這樣的情況:即后面的進程擁有前面每一個子進程的一個匿名套接字,但前面的進程則沒有后面任何一個子進程的匿名套接字足绅。
那么這個問題該如何解決呢捷绑?這就涉及到進程間傳遞文件描述符這個話題了∏饴瑁可以參考這里:進程之間傳遞文件描述符粹污。一個子進程被fork出來后,它可以依次向它之前被fork出來的所有子進程傳遞自己的描述符(匿名套接字對中的一個)首量。
通過這種機制,子進程之間也可以進行通信了壮吩。
Nginx中也就是這么做的。

Nginx中的具體實現(xiàn)

在ngx_process.c中蕾总,定義了一個全局的數(shù)組ngx_processes:
ngx_process_t ngx_processes\[NGX\_MAX\_PROCESSES\];
其中,ngx_process_t類型定義為:

typedef struct {
    ngx_pid_t           pid;
    int                 status;
    ngx_socket_t        channel\[2\];

    ngx_spawn_proc_pt   proc;
    void               *data;
    char               *name;

    unsigned            respawn:1;
    unsigned            just_spawn:1;
    unsigned            detached:1;
    unsigned            exiting:1;
    unsigned            exited:1;
} ngx_process_t;

在這里,我們只關(guān)心成員channel成員粥航,這個兩元素的數(shù)組即用來存放一個匿名套接字對。

我們假設(shè)程序運行后生百,有1個master進程和4個worker進程递雀。那么,對這5個進程而言蚀浆,每個進程都有一個4元素的數(shù)組ngx_processes[4]缀程,數(shù)組中每個元素都是一個ngx_process_t類型的結(jié)構(gòu)體,包含了相應(yīng)的某個worker進程的相關(guān)信息市俊。我們這里關(guān)心的是每個結(jié)構(gòu)體的channel數(shù)組成員杨凑。

繪制成表如下:


上表的每一列表示每個進程的ngx_processes數(shù)組的各個元素的channel成員。

其中摆昧,master進程列中的每一個元素撩满,表示master進程與對應(yīng)的每個worker進程之間的匿名套接字對。

而每一個worker進程列中的每一個元素,表示該worker進程與對應(yīng)的每個worker進程之間的匿名套接字對伺帘。當然這只是一個粗略的說法昭躺,與真實情況并不完全相符,還有很多細節(jié)需要進一步闡述伪嫁。

我們直接借助《深入剖析Nginx》领炫,直接看下圖的實例:


再次感謝《深入剖析Nginx》的作者高群凱,覺得在這里我沒法表達的比他更好了张咳。所以下面會引用很多該書中的內(nèi)容帝洪。

在上表中,每一個單元格的內(nèi)容分別表示channel[ 0 ]和channel[ 1 ]的值脚猾,-1表示這之前是描述符葱峡,但在之后被主動close()掉了,0表示這一直都無對應(yīng)的描述符龙助,其他數(shù)字表示對應(yīng)的描述符值族沃。

每一列數(shù)據(jù)都表示該列所對應(yīng)進程與其他進程進行通信的描述符,如果當前列所對應(yīng)進程為父進程泌参,那么它與其它進程進行通信的描述符都為channel[ 0 ](其實channel[ 1 ]也可以);如果當前列所對應(yīng)的進程為子進程常空,那么它與父進程進行通信的描述符為channel[ 1 ](注:這里書中說的太簡略沽一,應(yīng)該為如果當前列所對應(yīng)的進程為子進程,那么它與父進程進行通信的描述符為該進程的ngx_processes數(shù)組中漓糙,與本進程對應(yīng)的元素中的channel[ 1 ]铣缠,在圖中即為標粗的對角線部分,即[-1,7],[-1,9],[-1,11],[-1,13]這四對)昆禽,與其它子進程進行通信的描述符都為本進程的ngx_processes數(shù)組中與該其它進程對應(yīng)元素的channel[ 0 ]蝗蛙。

比如,[3,7]單元格表示醉鳖,如果父進程向worker0發(fā)送消息捡硅,需要使用channel[ 0 ],即描述符3盗棵,實際上channel[ 1 ]也可以壮韭,它的channel[ 1 ]為7,沒有被close()關(guān)閉掉纹因,但一直也沒有被使用喷屋,所以沒有影響,不過按道理應(yīng)該關(guān)閉才是瞭恰。

再比如屯曹,[-1,7]單元格表示如果worker0向master進程發(fā)送消息,需要使用channel[ 1 ],即描述符7恶耽,它的channel[ 0 ]為-1密任,表示已經(jīng)close()關(guān)閉掉了(Nginx某些地方調(diào)用close()時并沒有設(shè)置對應(yīng)變量為-1,這里只是為了更好的說明驳棱,將已經(jīng)close()掉的描述符全部標記為-1)批什。

越是后生成的worker進程,其ngx_processes數(shù)組的元素中社搅,channel[ 0 ]與父進程對應(yīng)的ngx_processes數(shù)組的元素中的channel[ 0 ]值相同的越多驻债,因為基本都是繼承而來,但前面生成的worker進程形葬,其channel[ 0 ]是通過進程間調(diào)用sendmsg傳遞獲得的合呐,所以與父進程對應(yīng)的channel[ 0 ]不一定相等。比如笙以,如果worker0向worker3發(fā)送消息淌实,需要使用worker0進程的ngx_processes[ 3 ]元素的channel[ 0 ],即描述符10,而對應(yīng)master進程的ngx_processes[ 3 ]元素的channel[ 0 ]卻是12猖腕。雖然它們在各自進程里表現(xiàn)為不同的整型數(shù)字拆祈,但在內(nèi)核里表示同一個描述符結(jié)構(gòu),即不管是worker0往描述符10寫數(shù)據(jù)倘感,還是master往描述符12寫數(shù)據(jù)放坏,worker3都能通過描述符13正確讀取到這些數(shù)據(jù),至于worker3怎么識別它讀到的數(shù)據(jù)是來自worker0老玛,還是master淤年,就得靠其他收到的數(shù)據(jù)特征,比如pid蜡豹,來做標記區(qū)分麸粮。

關(guān)于上段講的,一個子進程如何區(qū)分接收到的數(shù)據(jù)是來自哪一個進程镜廉,我們可以看一下Nginx-1.6.2中的一段代碼:

最后弄诲,就目前Nginx代碼來看,子進程并沒有往父進程發(fā)送任何消息娇唯,子進程之間也沒有相互通信的邏輯威根。也許是因為Nginx有其他一些更好的進程通信方式,比如共享內(nèi)存等视乐,所以這種channel通信目前僅作為父進程往子進程發(fā)送消息使用洛搀。但由于有這個架構(gòu)在,可以很輕松使用channel機制來完成各進程間的通信任務(wù)佑淀。

Nginx中的共享內(nèi)存

概述

共享內(nèi)存是Linux下提供的最基本的進程間通信方法留美,它通過mmap或者shmget系統(tǒng)調(diào)用在內(nèi)存中創(chuàng)建了一塊連續(xù)的線性地址空間,而通過munmap或者shmdt系統(tǒng)調(diào)用可以釋放這塊內(nèi)存。使用共享內(nèi)存的好處是當多個進程使用同一塊共享內(nèi)存時谎砾,在任何一個進程修改了共享內(nèi)存中的內(nèi)容后逢倍,其他進程通過訪問這段共享內(nèi)存都能夠得到修改后的內(nèi)容。
共享內(nèi)存可以說是最有用的進程間通信方式景图,也是最快的IPC形式较雕。兩個不同進程A、B共享內(nèi)存的意思是挚币,同一塊物理內(nèi)存被映射到進程A亮蒋、B各自的進程地址空間。進程A可以即時看到進程B對共享內(nèi)存中數(shù)據(jù)的更新妆毕,反之亦然慎玖。由于多個進程共享同一塊內(nèi)存區(qū)域,必然需要某種同步機制笛粘,互斥鎖和信號量都可以趁怔。
采用共享內(nèi)存通信的一個顯而易見的好處是效率高,因為進程可以直接讀寫內(nèi)存薪前,而不需要任何數(shù)據(jù)的拷貝润努。對于像管道和消息隊列等通信方式,則需要在內(nèi)核和用戶空間進行四次的數(shù)據(jù)拷貝示括,而共享內(nèi)存則只拷貝兩次數(shù)據(jù):一次從輸入文件到共享內(nèi)存區(qū)任连,另一次從共享內(nèi)存區(qū)到輸出文件。實際上例诀,進程之間在共享內(nèi)存時,并不總是讀寫少量數(shù)據(jù)后就解除映射裁着,有新的通信時繁涂,再重新建立共享內(nèi)存區(qū)域。而是保持共享區(qū)域二驰,直到通信完畢為止扔罪,這樣,數(shù)據(jù)內(nèi)容一直保存在共享內(nèi)存中桶雀,并沒有寫回文件矿酵。共享內(nèi)存中的內(nèi)容往往是在解除映射時才寫回文件的。因此矗积,采用共享內(nèi)存的通信方式效率是非常高的全肮。
Linux中,共享內(nèi)存可以通過兩個系統(tǒng)系統(tǒng)調(diào)用來獲得棘捣,mmap和shmget辜腺,分別屬于不同的標準,這不在本文的關(guān)注范圍之內(nèi)。mmap語義上比shmget更通用评疗,因為它最一般的做法测砂,是將一個打開的實體文件,映射到一段連續(xù)的內(nèi)存中百匆,各個進程可以根據(jù)各自的權(quán)限對該段內(nèi)存進行相應(yīng)的讀寫操作砌些,其他進程則可以看到其他進程寫入的結(jié)果。而shmget在語義上相當于是匿名的mmap加匈,即不關(guān)注實體文件存璃,直接在內(nèi)存中開辟這塊共享區(qū)域,mmap通過設(shè)置調(diào)用時的參數(shù)矩动,也可達到這種效果有巧,一種方法是映射/dev/zero設(shè)備,另一種是使用MAP_ANON選項。至于mmap和shmget的效率悲没,跟不同的內(nèi)核實現(xiàn)相關(guān)篮迎,不在本文關(guān)注范圍內(nèi)。
除了上面的簡單描述外示姿,本文不打算仔細介紹mmap和shmget的使用甜橱。有如下相關(guān)資料可以參考:
Linux環(huán)境進程間通信(五): 共享內(nèi)存(上)
Linux環(huán)境進程間通信(五): 共享內(nèi)存(下)
APUE,14.8,15.9

Nginx中的實現(xiàn)

那么,在Nginx中栈戳,到底是選用mmap映射到/dev/null岂傲,還是使用MAP_ANON選項調(diào)用mmap,或者是使用shmget呢子檀?看相關(guān)實現(xiàn)的代碼就會一目了然:
上面的代碼即是Nginx源代碼中的src/os/unix/ngx_shemem.c的全部內(nèi)容镊掖。可見褂痰,整個文件只是為了提供兩個接口:ngx_shm_alloc和ngx_shm_free亩进。而這兩個接口的實現(xiàn),按如下邏輯來決定:

如果當前系統(tǒng)的mmap系統(tǒng)調(diào)用支持MAP_ANON選項缩歪,則使用帶MAP_ANON選項的mmap归薛。
如果1不滿足,則如果當前系統(tǒng)mmap系統(tǒng)調(diào)用支持映射/dev/zero設(shè)備匪蝙,則使用mmap映射/dev/zero的方式來實現(xiàn)主籍。
如果上面1和2都不滿足,且如果當前系統(tǒng)支持shmget系統(tǒng)調(diào)用的話逛球,則使用該系統(tǒng)調(diào)用來實現(xiàn)千元。
看到這里,也許大家就有疑問了颤绕,如果當前3個條件都不滿足怎么辦诅炉,那就沒轍了蜡歹,ngx_shm_alloc接口沒有相應(yīng)的定義,只能在鏈接的時候就不成功了涕烧。

另外月而,關(guān)于上面三種情況的判斷,都是通過相應(yīng)的宏是否定義來進行的议纯,而相應(yīng)的宏的定義父款,是在auto/unix腳本中進行的,該腳本會寫一端測試程序來判斷相應(yīng)的系統(tǒng)調(diào)用是否支持瞻凤,如果支持憨攒,則在configure后自動生成的objs/ngx_auto_config.h文件中定義對應(yīng)的宏。

channel機制和共享內(nèi)存在Nginx中的使用情況

前面講Nginx中的channel機制時提到阀参,Nginx雖然提供了這種機制肝集,但目前很少用到,而共享內(nèi)存卻相對用的比較多了蛛壳。例如杏瞻,為了統(tǒng)計Nginx總體的http請求處理情況,需要跨越多個worker來計算衙荐,Nginx自帶的http模塊ngx_http_stub_status_module即主要依賴共享內(nèi)存的方式捞挥。

Ref:http://pureage.info/2015/03/28/ipc-of-nginx.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市忧吟,隨后出現(xiàn)的幾起案子砌函,更是在濱河造成了極大的恐慌,老刑警劉巖溜族,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讹俊,死亡現(xiàn)場離奇詭異,居然都是意外死亡煌抒,警方通過查閱死者的電腦和手機仍劈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來摧玫,“玉大人,你說我怎么就攤上這事绑青∥芟瘢” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵闸婴,是天一觀的道長坏挠。 經(jīng)常有香客問我,道長邪乍,這世上最難降的妖魔是什么降狠? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任对竣,我火速辦了婚禮,結(jié)果婚禮上榜配,老公的妹妹穿的比我還像新娘否纬。我一直安慰自己,他們只是感情好蛋褥,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布临燃。 她就那樣靜靜地躺著,像睡著了一般烙心。 火紅的嫁衣襯著肌膚如雪膜廊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天淫茵,我揣著相機與錄音爪瓜,去河邊找鬼。 笑死匙瘪,一個胖子當著我的面吹牛铆铆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辆苔,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼算灸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了驻啤?” 一聲冷哼從身側(cè)響起菲驴,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骑冗,沒想到半個月后赊瞬,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡贼涩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年巧涧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遥倦。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡谤绳,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出袒哥,到底是詐尸還是另有隱情缩筛,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布堡称,位于F島的核電站瞎抛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏却紧。R本人自食惡果不足惜桐臊,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一胎撤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧断凶,春花似錦伤提、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間秉颗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工冠王, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人舌镶。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓柱彻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親餐胀。 傳聞我的和親對象是個殘疾皇子哟楷,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354