文章首發於公衆號 松花皮蛋的黑板報linux
做者就任於京東,在穩定性保障、敏捷開發、高級JAVA、微服務架構有深刻的理解
![](http://static.javashuo.com/static/loading.gif)
nginx使用到的進程間通訊機制有三種,信號、套接字、共享內存。nginx
1、信號
在nginx當中,信號是操做系統與master進程的通訊方式。信號是用來控制master進程的一種手段。包括多鐘不一樣的關閉nginx的方式,更新應用配置文件等。具體在nginx當中經常使用的信號以下表所示。
TERM, INT
|
快速關閉,至關於nginx -s stop
|
QUIT
|
等待work進程處理完現有請求後,再關閉,至關於至關於nginx -s quit
|
HUP
|
從新加載配置文件,至關於nginx -s reload
|
USR1
|
從新打開日誌文件,至關於nginx -s reopen
|
USR2
|
平滑升級nginx
|
WINCH
|
關閉工做進程(等待work進程處理完現有請求後)
|
QUIT:關閉監聽套接字,不接受新的鏈接請求,處理完舊的請求再關閉。
HUP:該信號發送到master進程,master先檢查配置文件的語法,若是正確則打開新的日誌文件和監聽套接字,若此過程失敗則會回滾並繼續舊配置,若是此過程成功,則會啓動新的工做進程。
USER1:該信號經常使用於nginx切割日誌時,從新打開日誌文件,當master進程收到該信號後,會從新打開配置文件中配置的日誌文件,若是日誌文件不存在則會新建一個日誌文件。由於worker進程須要有對日誌文件的讀寫權限,因此若是master和worker的用戶不一致,則須要把日誌文件的擁有者改爲worker進程。而後master進程關閉舊日誌文件,並通知worker進程使用新的日誌文件,實際的操做就是,master進程把USER1信號發給worker進程,worker進程接收到信號後,從新打開日誌文件。
USER2:平滑升級nginx
操做步驟:
1.發送信號給master進程
kill -USR2 $(cat /export/kong/pids/nginx.pid)
這一步會將.pid文件重命名爲.oldbin,而後,執行
2.啓動新版本nginx
3.結束舊版本master進程
kill -QUIT $(cat /export/kong/pids/nginx.pid)
2、套接字
套接字是master進程和worker進程通訊的方式,可是目前只有master經過套接字發送消息給worker進程,還未用於worker進程發送消息給master進程。
舉例來講,當nginx啓動時,
1)master建立socket對
master在fork worker進程前,先調用socketpair,建立一個socket對用來master與worker進程間的通訊。這個socket就是一個元素個數爲2的數組channel,channel[0]用於master進程寫入,channel[1]用於worker進程讀入。
2)master建立worker進程
master進程根據配置文件中設置的worker進程數建立work進程。
3)worker進程將套接字加入epoll中
這樣worker進程在處理http請求時也能夠接收到master進程向它發送的消息了。
4)worker進程循環
3、共享內存
共享內存是最快的通訊方式,是worker進程之間的通訊方式。須要共享的數據就須要用到共享內存,例如,http鏈接數,每一個worker進程修改的都是共享內存中的數據,該數據是全局變量,對全部的worker進程是共享的。
nginx經過ngx_shm_t這個結構體管理共享內存,方法只有分配和釋放。nginx對linux的分配內存 mmap和釋放內存方法munmap進行了封裝,不同的地方是nginx不從文件中映射,只從內存中開闢一段連續的地址空間做爲共享內存。封裝後的nginx分配內存方法是 ngx_shm_alloc,釋放內存方法是 ngx_shm_free。
其實master和worker進程也能經過共享內存通訊,在master進程fork worker進程以前,先在內存中開闢一塊共享內存,而且映射到本身進程地址空間中的共享內存區,而後,調用fork,這樣派生出來的worker進程能夠繼承到這塊共享內存區,這樣master和worker之間也能夠經過共享內存通訊。
文章來源:www.liangsonghua.me數組
做者介紹:京東資深工程師-梁鬆華,在穩定性保障、敏捷開發、JAVA高級、微服務架構方面有深刻的理解架構