1、平滑升級步驟nginx
一、重命名以前的sbin/nginx文件,將新的nginx文件放到sbin/目錄下socket
#mv ./sbin/nginx ./sbin/nginx.old函數
#cp ~/nginx ./sbin/源碼分析
二、向正在運行的nginx發送USR2信號啓動新的nginx,這個時候新老nginx都會接收請求,看那一個進程能搶到鎖,搶到鎖的worker進程能夠accpet新請求ui
#kill -USR2 `cat nginx.pid`spa
三、觀察新的nginx運行無誤後,向舊nginx發信號 中止舊nginx的運行3d
#kill -QUIT `cat nginx.pid.oldbin`unix
2、源碼分析blog
1,nginx啓動時 設置信號監聽函數,監聽信號隊列
src/core/nginx.c
368行 ngx_init_signals函數 設置要監聽的信號,和信號的處理函數
src/core/nginx.c
291-293行 信號爲sig->signo,對應的處理函數爲sig->handler
sig的定義以下
QUIT和USR2的信號處理函數都爲 ngx_signal_handler
對應的流程圖爲
二、master進程經過sigsuspend掛起在信號監聽處
3,向master進程id發送USR2信號
ngx_signal_handler處理USR2信號
src/os/unix/ngx_process.c
372行 設置了ngx_change_binary=1
master進程接收到信號,從掛起狀態恢復,繼續執行
src/os/unix/ngx_process.c
277行 ngx_exec_new_binary經過fork啓動新的nginx bin文件
src/core/nginx.c
589行 ngx_set_evviroment 設置新nginx bin的環境變量
640行 ngx_rename_file 經過rename函數將nginx.pid文件重命名爲nginx.pid.oldbin
651行 ngx_execute 啓動新的bin文件
因爲nginx老master進程fork出的新nginxmaster進程,他們能夠監聽同一個端口,因此新nginx和老nginx能夠同時監聽端口,具體誰執行看哪個worker子進程搶到了鎖,能夠accpet新鏈接
src/os/unix/ngx_process.c
src/os/unix/ngx_process.c
src/os/unix/ngx_process.c
對應的流程圖以下
四、向老的nginx進程發送QUIT信號,從容關閉
master進程收到QUIT信號後,將ngx_quit置爲1
master進程接收到信號,從掛起狀態恢復,繼續執行
209行 ngx_signal_worket_processes 向worker進程發送 NGX_SHUTDOWN_SIGNAL(QUIT)信號
215行 ngx_close_socket 主進程關閉監聽的socket
src/os/unix/ngx_process_cycle.c
504行 經過kill函數向全部worker進程發送信號
五、worker進程收到NGX_SHUTDOWN_SIGNAL(QUIT)信號
src/os/unix/ngx_process.c
360行 worker進程將ngx_quit置爲1
worker進程收到信號後從epoll_wait中喚醒從ngx_process_events_and_timers函數中恢復,
710-714行 發現ngx_quit=1後將ngx_quit恢復爲0,ngx_exiting置爲1,
713行 經過ngx_close_listening_sockets關閉處理的socket
609行 下一次循環發現ngx_exiting=1後,處理隊列中的已有事件和超時事件,發現沒有要處理的事件了,就經過ngx_worker_process_exit退出worker進程
src/os/unix/ngx_process_cycle.c
1024行 調用各個模塊的exit_process方法
1067行 銷燬內存池
對應的流程圖以下
六、子進程退出後,做爲父進程的master進程會收到SIGCHLD信號
src/os/unix/ngx_process.c
387行 父進程收到SIGCHLD後將ngx_reap置爲1,
437行 發現信號是SIGCHLD後執行ngx_process_get_status函數判斷worker子進程是正常退出,仍是異常退出
src/os/unix/ngx_process.c
494-499行 若是發現worker子進程若是是正常退出的,會將exited置爲1
master進程接收到信號,從掛起狀態恢復,繼續執行
176行 發現ngx_reap=1後,ngx_reap_children函數判斷是否須要重啓worker進程
若是worker是由於收到了quit信號正常退出的,全部worker進程退出時,live=0
183行 live=0 而且收到了ngx_quit信號 經過ngx_master_process_exit關閉master進程
src/os/unix/ngx_process_cycle.c
619 若是worker至今纔是由於意外退出的,而且能夠重啓,則調用ngx_spawn_process從新啓動一個worker子進程
642 若是有worker進程還在運行則live=1 若是所有的worker子進程都已經退出則live=0
src/os/unix/ngx_process_cycle.c
656行 ngx_delete_pidfile 刪除pid文件
666行 ngx_close_listening_sockets 關閉監聽端口
685行 銷燬內存池
686行 退出
對應的流程圖以下