陳 濤,任海蘭
(武漢郵電科學研究院 湖北 武漢 430074)
Web服務器常常需要處理多個并發請求,針對每一個請求,Web服務器會有相應的并發程序來執行相關操作。
這一過程中,使用進程是構造并發程序最簡單的方法:為了實現進程間的信息交互,它們必須使用顯式的進程間通信((IPC)機制,由于進程控制和IPC的開銷很高導致基于進程的設計運行速度往往比較慢[2-4]。
為解決進程間信息共享而造成的高開銷問題,本文采用多線程池的并發設計,利用信號量訪問共享變量,使用生產者一消費者模型降低線程開銷,從而提高系統訪問速度和資源利用率。
目前主流boa服務器主要基于多進程來構造并發程序。首先由父進程去接受客戶端的連接請求,然后創建一個新的子進程去為每一個客戶端提供服務。這種父子進程會共享文件表,但是不共享用戶地址空間。基于這種特性,這類進程中不會存在一個進程覆蓋另一個進程的虛擬存儲器,但是這也使得進程共享狀態信息變得更加困難,因而基于多進程Web服務器引入了IPC機制。
在面對大量并發處理請求時,由于進程機制和IPC機制開銷大,會使得服務器延時效果明顯。
線程是程序執行流的最小單元,線程由內核自動調度。一個進程里可以同時運行多個線程,每個線程都有自己的線程上下文,包括一個唯一的棧、棧指針、條件碼、程序計數器、整數線程ID、通用目的寄存器,運行在同一個進程里的所有線程共享該進程的整個虛擬地址空間。
同時,線程執行又區別于進程執行,在于:1)較于進程環境,一個線程環境擁有的系統資源極少;2)線程不構成父子層次關系。
在線程池技術中,我們在任務還沒有到來之前,創建一定默認數量的線程。這些線程均處于睡眠狀態,不消耗CPU,只占用較少的內存空間。當輪詢到有請求到來后,線程池將會分配給這次請求一個空閑的線程,進行執行。
當預先創建的線程都已處于運行狀態,即并發請求數量多于線程池中最少空閑線程數時,線程池將會自由創建一定數量的新線程,用于處理更多的并發請求。當系統比較閑的時候,線程池就會移除一部分已經停用的線程,以減少系統負荷。
線程池技術由于具有節省系統開銷,信息共享容易,完成時間短的優點非常適合處理大數量的并發請求。
信號量模型只支持P,V兩種操作,且均為原子操作,要么都不執行,要么全部執行[5-6]。
1)P(s):如果 S 為非零,那么 P 操作就將 S 的值減 1,然后返回。如果S為零,那么當前進程(線程)將會被阻塞,直至S值不為0;當S值不為0,被阻塞的進程會重啟。重啟之后,S的值減1。
2)V(s):對S進行操作,就是將 S的值加 1。 為實現內核同一時刻對共享變量的互斥訪問,將信號量(初始值為1)與共享變量聯系起來,用P和V操作將相應的臨界區保護起來,從而使得在任何時間點上,信號量操作確保對臨界區的互斥訪問。
調度對共享資源的訪問是信號量的另一個重要作用,在某一時刻,程序中某個條件一旦為真,一個線程會通過信號量來告知其他線程允許訪問。
圖1所示的生產者—消費者模型是一個經典的信號量調度同步示例。生產者和消費者線程共享一個有限單元的緩存區。

圖1 生產者一消費者模型Fig.1 Producer-consumer model
生產者線程不斷地生產新的項目并把它們插入到緩存區中;消費者線程則不斷地從緩存區中取出這些項目,然后消費它們。模型中允許有數量不同的生產者和消費者。
在本次設計中,生產者線程,消費者線程均來自于線程池。主程序輪詢到請求到來后,線程池會給請求分配一個空閑的線程,進行相關任務的執行。
由于插入和取出兩種操作涉及到對緩存區共享變量的更新,所以需要保證它們的互斥訪問。除此之外,還需要考慮調度對緩存區的訪問,例如,當緩存區為空的時候,消費者將被阻塞,直到不為空的時候被喚醒;同理,當緩存區滿的情況下,生產者應該被阻塞,等待有空的位置出現。
在Web服務程序中,通常將收到的客戶請求分為如下4個部分來進行處理:
1)監聽服務端口,與客戶端建立連接;
2)解析URL與報頭;
3)靜態/動態請求處理;
4)消息的應答機制。
本文基于多線程池并發Web服務器設計模型如圖2所示。

圖2 多線程池并發服務器模型Fig.2 Concurrent multi-threaded server model pool
圖2 中每一個數據隊列均有對應的線程池對其進行輪詢。在每個線程池中,都有一定數量的處于睡眠狀態的線程。主程序在監聽到請求后,將請求消息放入請求解析數據隊列。線程池輪詢到有新請求,會給每個消息請求分配一個空閑線程。當有多個并發請求到來時,將會出現報文解析線程組。用戶請求信息完成報文解析處理后,將進入事物處理請求隊列。請求在事物處理隊列和消息回復隊列中的處理機制一致。
這樣一來,每種任務線程最多只需關心自己的處理程序,與和自己相關的幾個消息隊列即可。這種方式使服務模塊化,易于管理和維護。流水線的工作方式使服務器的多任務處理性能得到進一步優化。
根據網絡應用程序的開發模型和HTTP協議,Web服務器設計實現的主要操作流程及功能如下:
1)主函數處理流程:緩沖I/O初始化->打開監聽端口->建立線程組->監聽請求連接->將連接放入線程組->從連接組中取出連接->執行指定服務。
2)服務器響應請求流程:讀取請求->獲取請求方法、URL、和版本->判斷請求方法->解析URL->判斷訪問權限->放入事務請求處理隊列。
3)解析 URL流程:根據 CGI判斷靜態/動態標服務->拷貝URL到FILENAME中->添加默認文件home.html->返回靜態/動態標志。
4)為客戶端提供靜態服務流程:打開指定文件->拷貝到虛擬內存->拷貝虛擬內存至指定賬戶->關閉描述符、釋放虛擬內存。
5)為客戶端提供動態服務流程:構造線程來執行CGI程序->通過調用不同的參數,來產生細節不同的動態文檔->等待線程執行結束,回收資源。
依據上述設計理念,Web服務器在Linux系統下采用C語言編寫,用gcc編譯實現。
圖3給出了訪問靜態頁test.html的效果示意圖,圖4給出了訪問動態頁cgi-bin/add的效果示意圖。測試證明該Web服務器能實現服務器的基本功能,即在服務器端接收到HTTP請求后,可以予以響應。

圖3 靜態頁面Fig.3 Static pages

圖4 動態頁面Fig.4 Dynamic pages
Apache中有個名為ab的程序,可以對Apache其它類型的服務器進行網站訪問壓力測試。本文使用該軟件來進行壓力測試,兩次測試中,均向目標Web服務器累計發出1 000次請求,每次100個請求并發(模擬 100人同時訪問),圖5為普通嵌入式Boa服務器測試結果截圖,圖6為改進后Web服務器測試結果截圖。

圖5 普通web服務器測試結果Fig.5 Results of ordinary web server test

圖6 改進后Web服務器測試結果Fig.6 Results of improved web server test
這兩份性能測試單有兩個重要測試指標:1)每秒鐘平均處理的請求數;2)每個線程下的一組請求(100個)平均消耗時間。改進服務器前后數據分別為:7.35/9.19(改進后),13 607.549 ms/10 884.814 ms(改進后)。
通過數據可以看出改進后的Web服務器能有效降低系統開銷,大幅度提高Web服務器的系統資源利用率和服務效率。
基于進程或單純基于線程服務器普遍會存在著利用率不高、資源消耗大等問題。本文設計的基于多線程池并發Web服務器,利用生產者一消費者模型和多線程池高效率實現了資源調度及共享。設計實現的改進Web服務器能實現Web服務器的基本功能,能接受一定規模的并發客戶請求并予以響應,具有較高的服務效率。后續還有一些工作需要完善,如進一步完善用戶的動態請求處理,加強對請求頭信息的分析等。
[1]Randal E Bryant,David O'Hallaron.Computer systems:a programmer's perspec;tive[M].New Jersey:Prentioe Hall Publisher.2003.
[2]張根寶,胡杰.Linux集群環境下監控Web服務器的Shell腳本設計[J].化工自動化及儀表,2010,37(10):99-101.ZHANG Gen-bao,HU Jie.Shell script design of monitoring web server under linux cluster environment[J].Control and Instruments in Chemical Industry,2010,37(10):99-101.
[3]張估,曹奇英.Web服務器負載壓力模型及其優化原則[J].計算機應用軟件與軟件,2010,27(12):139-141.ZHANG Gu,CAO Qi-ying.Load pressure model and optimization principles of web server[J].Computer Applications and Software,2010,27(12):139-141.
[4]胡中棟,曾志勇.基于多路徑的DSR路由協議改進[J].江西理工大學學報,2011,32(3):45-48.HU Zhong-dong,ZENG Zhi-yong.Improved DSR-routing protocol based on multipath[J].The Jiangxi University of Science and Technology Journal,2011,32(3):45-48.
[5]Richard Stevens W,Bill Fenner.Unix network programming volume 1:the Sockets networking API,third edition[M].New Jersey:Prentice Hall Publisher,2003.
[6]Tanenbaum A.Modern operating systems,third edition[M].New Jersey:Prentice Hall Pnhlisher,2007.