羅清波



關鍵詞:LNMP;Moodle;服務器;PHP;高并發;抗擁塞
中圖分類號:TP393 文獻標識碼:A
文章編號:1009-3044(2023)02-0069-03
Moodle是基于PHP語言開發的免費開放學習管理系統(LMS),由于采用了組件化管理,教學手段靈活,功能齊全,所以被國內外教育機構普遍使用。LNMP是當今比較流行的免費開源Web服務框架,該架構涉及技術范圍廣,安裝和配置相對復雜。如果沿用傳統的配置方式,不能最大程度發揮Moodle教學服務器的性能,而且系統在安全性和高效性方面也得不到保證。服務器在高并發情況下網頁很容易卡死,甚至會導致數據庫崩潰,所以對LNMP架構進行優化是亟待解決的問題[1]。
1 LNMP 架構介紹
LNMP架構由Linux 內核服務器、Nginx 服務器、Mysql數據庫系統、PHP腳本服務器組合而成。Nginx 是高性能輕量級反向代理服務器,Mysql是一款安全、跨平臺、高效的數據庫系統,PHP腳本服務器用于編譯和執行PHP腳本。LNMP架構數據請求與返回如圖1所示[2]。
從圖1可以看出,數據總是從客戶端瀏覽器經過Nginx服務器、php-fpm服務器、MySQL數據庫后,又按原路返回,形成閉環回路,為了提高Moodle教學服務器的性能,需要對LNMP 架構的各個環節進行優化處理。
2 Moodle 教學平臺介紹
Moodle是由澳大利亞教師Martin發起的開放學習管理系統(LMS)[3] 。該學習管理系統采用模塊化組件設計,目前系統組件種類高達1967個,提供全方位教學手段。教師可以使用這些組件完成不同的教學方案,可以實現不同的教育教學模式。這些組件安裝方便,操作簡單,與原有的系統共存使用。目前世界上多個國家近千所高校和教科研機構都采用Moodle 作為網絡在線教學平臺[4]。
3 服務器處理速度優化
通過開啟Opcache 和TMPFS,優化Mysql 數據庫的InnoDB,優化PHP進程,開啟gzip傳輸、開啟Cron.php定時運行,可以大幅度提高Moodle教學服務器的處理速度。
3.1 開啟Opcache
PHP作為一種解釋性語言,每次運行都會將代碼進行加載解析,運行結束后再釋放,下次運行又要重新加載解析再釋放。這種方式顯然不適合高并發運行的Moodle教學服務器。
為了避免這樣的問題出現,PHP開發了Opcache 組件,系統啟用Opcache后,在解析過程中可以將一些相同并且重復的中間件保存在Opcache緩存中,下次加載時無須再編譯,加快了代碼的執行效率,降低了CPU的消耗,減少了PHP網頁的響應時間。
3.2 開啟TMPFS
服務器的內存儲器訪問速度比磁盤的訪問速度要快得多,如果將Moodle網站的程序文件和數據庫直接放置在內存儲器中,Moodle站點的處理速度就會大幅度提高。將磁盤文件存儲在內存儲器中的方法是啟用TMPFS緩存系統。TMPFS的特點是暫時存儲、高速讀寫和動態收縮。TMPFS默認的初始化存儲空間為物理內存的一半,這部分存儲空間不會被獨占,僅在掛載存儲文件后才會占用。掛載命令:mount-tTMPFS -o size=65536M,mode=0755 tmpfs /var/www/cache。
3.3 多進程處理
為了充分發揮CPU的多核特征,可以將Nginx和php-fpm設置為多進程模式,提高處理效率。Nginx通過反向代理功能將用戶瀏覽器的PHP動態請求分配給空閑的Nginx工作進程。Nginx并不參與PHP的請求編譯和運行工作,而是交由php-fpm 管理進程處理。php-fpm將具體的任務分配給空閑的Fast-CGI協議[5],由Fast-CGI協議負責編譯和運行,并與后臺數據庫實現數據交互,最后將結果以超文本形式返回給用戶瀏覽器。
Nginx 通過配置worker_ processes 的值開啟多進程工作模式。這個數值必須與CPU的內核數相匹配,如果設置不恰當會使服務器假死。
php-fpm 進程管理有三種模式,分別為onde?mand、dynamic和static。配置文件地址為/etc/php/7.2/php-fpm.conf。
如果將配置文件中pm參數設置為Ondemand(按需模式),在php-fpm開始啟動時,不會創建任何進程,當有連接請求時才會創建。進程數量取決于pm.max_children設定值,如果空閑進程時間超過pm.pro?cess_idle_timeout設定的值,進程將關閉,一般默認設置為10ms。
如果將配置文件中pm參數設置為Dynamic(動態模式),在php-fpm 啟動時,初始啟動的個數為pm.start_servers 設定值,在運行過程中動態調整進程數量,進程數量最大取決于pm.max_children設定值。
如果將配置文件中的pm參數設置為Static (靜態模式),php-fpm開始啟動后始終保持pm.max_children 設定值,在運行期間也不會擴容。
Moodle 教學服務器采用static 靜態模式。一般php-fpm進程占用最大內存空間為30M,在靜態模式下pm.max_children的值可設置為物理內存Mem/30M,但考慮到操作系統、Nginx、MySQL都需要占用內存,所以php-fpm進程數可以設為物理內存Mem/30M/2。
3.4 存儲引擎InnoDB
InnoDB作為MySQL數據庫的默認存儲引擎被廣泛應用。MySQL數據庫接收SQL請求后,通過InnoDB存儲引擎與磁盤存儲文件進行交互。在LNMP架構中,和數據庫有關的用戶請求都要通過InnoDB存儲引擎,因此,優化InnoDB 存儲引擎的性能決定了LNMP架構的性能。InnoDB存儲引擎參數設置文件為/etc/mysql/my.cnf,設置參數如表1所示。
在InnoDB存儲引擎中,通常情況下將日志文件組設置為3,為了避免日志覆蓋導致緩沖池的不必要刷新,每個日志文件的大小最好設置為InnoDB緩沖池的25%。為了防止線程設置過高產生抖動,一般將線程并發數設置為16。讀線程和寫線程是InnoDB存儲引擎用來同步操作系統中的讀寫操作,一般設定參數值為8。控制Innodb事務日志寫入的參數值設置為2,確保日志及時寫入磁盤并刷新,這樣設置不僅可以使InnoDB存儲引擎的日志存盤時間變小,而且保證了數據的安全。
3.5 Cron.php 計劃任務定時運行
在Moodle教學服務器中,Cron.php主要用于計劃執行課程備份、郵件收發、臨時文件清理、課程整理、刪除不需要的檢測事件等,設置為每隔5分鐘執行一次效果最佳。
通過命令sudo apt-get install cron安裝Cron,然后用命令crontab -e 打開活動列表,將下面的命令添加到Cron活動列表中,實現每5分鐘執行一次cron.php 程序文件,password的值通過Moodle管理后臺獲取。
*/5 **** wget –q –o /dev/null
https://ke.qingbosoft.cn/admin/data/cron.php?pass?word=”*****”
4 抗擁塞處理
當服務器遇到高并發請求時,會使服務器響應速度變慢,數據庫崩潰,甚至服務器宕機等事故發生,所以需要對服務器進行抗擁塞處理。出現擁塞的原因主要有兩個方面,一方面MySQL數據庫采用默認的單線程處理模式,另一方面PHP進程數開啟過大,使數據庫同步連接數變大。抗擁塞處理的方法是對MySQL 數據庫啟用線程池,并配置合理的PHP 進程數。
4.1 Thread Pool 線程池優化
PHP 與MySQL 建立連接后,PHP 通過MySQL 的線程機制來處理請求。MySQL默認的線程調度方式為One-Connection-Per-Thread單線程模式,當使用單線程處理每個客戶的連接請求時,對于每一個數據庫連接,MySQL 都要創建獨立的線程服務,請求結束后再銷毀掉,當數據庫遇到高并發時,線程頻繁創建和銷毀,服務器的性能會大幅度降低。
為了解決這個問題,Oracle 公司推出了線程池(Thread Pool Plugin)方案。線程池通過緩存并重用方式,將連接分配給不同的組隊列,對用戶的SQL 請求進行排隊處理,減少上下文切換次數,通過隊列機制縮短了處理請求的時間。同時,線程的重用降低了頻繁的連接請求次數,即使在訪問高峰期,數據庫仍然能保持高吞吐量,有效解決擁塞問題。Thread Pool線程池的參數配置文件為/etc/mysql/my.cnf,配置參數如表2所示。
4.2 PHP 進程數配置
在Moodle教學服務器中,用戶請求通過Nginx發送到php-fpm,然后以隊列的形式發送給多個Fast-CGI 進行處理,每個Fast-CGI 與MySQL 建立連接,MySQL數據庫通過Thread Pool線程池處理Fast-CGI 的SQL請求。
當Nginx的pm參數設置為Dynamic動態模式時,如果有1024 個用戶同時訪問Moodle 應用服務器,MySQL數據庫就需要創建1024個鏈接與php-fpm所創建的1024個Fast-CGI相連,并同時處理1024個工作線程,這樣會造成Mysql數據庫阻塞,使服務器無法高效運行。
為了提高服務器的運行效率,需要固定PHP的進程數目。所以將Nginx的pm參數設置為Static靜態模式。pm.max_children進程值可以根據MySQL數據庫的最大允許連接數來推算。如果MySQL數據庫的每個連接所占內存容量最大為36.8MB,而分配給數據庫的總內存為36G, 則MySQL數據庫的最大連接數可以設置為1000,php-fpm中pm.max_children進程數可以設置為1000。但一般情況下Fast-CGI進程占用內存最大值為30MB,而且還要考慮到服務器其他應用的開銷,所以pm.max_children進程數的值一般設置為64 就夠用了[6]。
5 服務器性能測試
5.1 性能測試
使用Google瀏覽器自帶的Network工具對Moodle 應用服務器進行整體性能測試,測試服務器Request 和Response的請求響應耗時。
發現優化前加載https://ke.qingbosoft.cn/course 課程頁面,PHP訪問MySQL數據庫需要耗時350ms左右,而通過系統優化處理后,Moodle課程頁面加載耗時總體穩定在146ms左右,處理速度提高了2.6倍,服務器性能得到了很大程度的提升[7]。
5.2 抗擁塞檢測
通過使用Sysbench壓力測試工具對MySQL數據庫進行只讀壓力測試。分別設置MySQL數據庫為單線程(One-Connection-Per-Thread)模式和線程池(Thread Pool)模式,對兩種模式進行高并發條件下TPS數據吞吐量測試,測試結果如圖2所示。
檢測結果表明,伴隨著并發數目的不斷增大,單線程模式下TPS數據吞吐量急速下降,當并發數達到5000時,單線程TPS數據吞吐量幾乎為0,而線程池模式的TPS 數據吞吐量始終穩定在6500~7100左右。所以使用線程池模式,可以很好地解決數據庫在高峰訪問時的擁塞問題,有效提高了Moodle教學服務器的訪問速度[8]。
6 結束語
本文詳細論述了基于LNMP架構的Moodle教學服務器的構建與優化,對服務器的LNMP架構進行深度優化,目前應用在Moodle在線教學平臺(網址https://ke.qingbosoft.cn)上,服務器性能穩定可靠,起到了很好的教學應用效果。
文中提出的構建及優化方案對搭建基于Linux內核操作系統的網站服務器具有很好的參考價值。隨著科技不斷進步,受新冠肺炎疫情影響,更多的教育機構都在開發和搭建自己的在線教學系統,人們對基于LNMP架構的應用服務器進行不斷地探索與研究,必將使其能更加安全、快速、高效地提供服務。