前言
如果已經在LNMP架構下工作2-3年時間,這個階段我們對自己常用的技術棧的工作原理一定需要有一個基本的認識。一方面,可以去學習這些優秀軟體的設計思路,另一方面,可以為分析系統瓶頸和系統優化打好基礎。今天我們就來看看php-fpm/nginx/redis/mysql的程式模型。
php-fpm的程式模型
php-fpm採用了master-worker多程式的模型,其次與php-cgi相比提供了更好的程式管理方式。php-fpm的程式模型示例圖如下:
master主程式的主要任務:
- 監聽socket(TCP/IP或者Unix Domain Socket)
- 管理子程式
master通過如下的訊號來對程式進行管理:
SIGINT/SIGTERM 退出訊號
SIGQUIT 優雅退出訊號
SIGUSR1 重新載入日誌檔案訊號
SIGUSR2 平滑重啟訊號
SIGCHLD 回收子程式資源訊號(wait/waitpid防止異常退出的子程式變成殭屍程式,殭屍程式會佔用pid等核心資源)
複製程式碼
worker工作程式的主要任務:
- accept請求
- 執行具體的php指令碼
多程式(單執行緒)併發模型
nginx的程式模型
同樣,nginx也採用了master-worker多程式的模型,程式模型圖如下所示:
但是與php-fpm主要的不同的是:
- master程式不負責監聽埠
- worker程式自身監聽埠(多個程式會產生驚群效應,nginx使用互斥鎖使同一時刻只有一個程式去listen埠)
master通過如下的訊號來對程式進行管理:
SIGINT/SIGTERM 退出訊號
SIGQUIT 優雅退出訊號
SIGHUP 平滑重啟訊號
SIGUSR1 重新載入日誌檔案訊號
SIGUSR2 平滑升級訊號
SIGWINCH 優雅退出某個worker程式訊號
複製程式碼
多程式(單執行緒)和多路I/O複用併發模型
redis的程式模型
redis採用的是單程式的模型,如下圖所示:
但是,redis需要實現持久化,持久化的方式一般有兩種RDB(寫快照)/AOF(寫命令),持久化的過程redis會fork一個子程式來完成,目的不阻塞master工作程式。如下圖所示:
單程式(單執行緒)和多路I/O複用併發模型
mysql的程式模型
mysql談程式模型其實還是不合適,mysql主要採用的是多執行緒的架構。
多執行緒併發模型
總結
php-fpm多程式,符合php語言的設計思想「簡單」。程式間資源隔離,簡單且複雜性底,反之相對於而言高流量下效能會不是很好。
nginx多程式,worker去監聽埠,一方面,使得master專注於程式管理;另一方面,提高服務的健壯性,如果有一個worker掛了別的worker還可以繼續處理請求;其次,發揮計算機多核的優勢。
redis單程式,採用I/O多路複用效能已經足夠的好,redis基本都是記憶體操作,不使用多執行緒,避免了大量競爭,簡化了系統的複雜度。其次,redis也沒涉及複雜的計算場景,單核足夠使用。
mysql多執行緒,按照我目前的理解,絕大多數常用的mysql引擎的效能瓶頸是在於磁碟IO,多執行緒技術已經足夠滿足併發需求。
思考
從上面看來,不同的系統設計,根據它的運用場景都採用了符合它們自身需求的設計。比如,php的簡單;nginx的高可用高效能的web server;redis高效能的nosql;mysql大量的磁碟操作。
這些系統使用的多程式,多執行緒,協程,I/O多路複用(select/poll/epoll)等技術手段都是指引我們去優化我們系統的方向,這些優秀系統都為我們的設計思路提供了很好的案例,去提高併發能力,解決網路IO、磁碟IO問題。這些都是我們現在以及未來需要去理解和消化的東西。
最後,以上內容有理解不對的地方,歡迎大家及時指正,非常謝謝~
附錄
常見linux訊號和數字對映表:
訊號 | 數字(LINUX) | 含義 |
---|---|---|
SIGKILL | 9 | force kill |
SIGINT | 2 | interrupt |
SIGQUIT | 3 | quit graceful |
SIGTERM | 15 | terminate |
SIGHUP | 1 | hang up |
SIGUSR1 | 10 | user defined |
SIGUSR2 | 12 | user defined |