摘 要: 隨著計算機技術和網(wǎng)絡技術的快速發(fā)展,以嵌入式設備為主的監(jiān)控系統(tǒng)、信息家電和通信設備被廣泛使用,嵌入式Web服務器則是其中關鍵的技術設備。本文介紹了Web服務器的結構設計,并對系統(tǒng)中采用的關鍵技術及其實現(xiàn)進行了論述。
關鍵詞: 嵌入式;Web服務器
Web應用程序與傳統(tǒng)應用程序相比,具有許多特點和優(yōu)勢, 隨著Web應用程序工具與技術的快速發(fā)展,Web應用程序的應用也越來越廣泛。同時,由于Internet技術的滲透,嵌入式系統(tǒng)正變得越來越智能化并具有越來越多的網(wǎng)絡友好特性,嵌入式Web服務器的應用也越來越廣泛,它可以廣泛地用于各種監(jiān)控系統(tǒng)、信息家電及智能家居系統(tǒng)、通信設備等領域[1]。
1 嵌入式Web服務器結構
嵌入式Web服務器應有如下一些的設計目標:
(1)借助HTTP協(xié)議統(tǒng)一并通用化設備或終端的訪問接口。
(2)實現(xiàn)對HTTP 1.0和HTTP l.1的支持,實現(xiàn)HTTP的部分方法(GET、POST、HEAD等),支持Basic、Digest加密的認證,支持服務器“推”技術等。
(3)集成簡單的應用服務器功能,便于應用開發(fā)人員方便地構建基于嵌入式Web服務器的應用系統(tǒng)。
(4)支持多種協(xié)作接口,嵌入式Web服務器應該可以以各種接口方式與相應的模塊進行集成,這主要是通過動態(tài)庫來實現(xiàn)。
(5)支持多種傳輸方式,嵌入式Web服務器需設計一個連接層,該層用來抽象各種具體的傳輸方式,提供統(tǒng)一和標準的連接服務,Web服務器本身只依賴一個可靠的傳輸通道,并不限定是基于TCP的。
根據(jù)以上嵌入式Web服務器的設計目標,Web服務器的核心在于其HTTP引擎和分析引擎,前者主要負責HTTP協(xié)議請求和響應消息處理,后者用于解析網(wǎng)頁中的嵌入式標記,以實現(xiàn)動態(tài)內容支持。圖1是基于嵌入Web服務器的應用系統(tǒng)框架,圖中的瀏覽器是客戶端,用戶接口庫是嵌入式Web服務器和設備的其他控制等部分的接口,由應用開發(fā)人員提供。虛線框中的是嵌入式Web服務器的框架結構,該設計的基本思想來源于經(jīng)典的MVC(模型-視圖-控制)模型,這里把HTTP引擎和分析引擎作為控制器,待分析網(wǎng)頁和靜態(tài)網(wǎng)頁是視圖,而用戶接口庫則是作為模型,專注于業(yè)務邏輯。利用控制器來分離模型和視圖,實現(xiàn)模塊間松散耦合的效果,可以提高系統(tǒng)靈活性、復用性和可維護性[2]。
1.1 HTTP引擎
HTTP引擎主要負責對客戶訪問的過濾和權限檢查,HTTP請求和響應消息的接收和發(fā)送,會話(session)管理,客戶認證和授權,消息的封裝、解析和消息安全性檢查。
首先,HTTP引擎進行初始化工作,為該設備站點初始化相應的配置數(shù)據(jù)結構,如設置站點基本信息、建立用戶賬號、初始化各目錄的訪問權限、初始化嵌入式標記的映射定義等。然后HTTP引擎接收請求連接,提取訪問客戶的客戶端的信息(如IP等),根據(jù)配置文件的站點過濾設置進行篩選,如不允許,則返回出錯頁面,結束處理。
為了加強嵌入式應用的安全管理,嵌入式Web服務器默認設置:假定任何訪問客戶均需提供用戶名和口令,接著進行客戶認證,在客戶會話超時后的請求或初次發(fā)送請求時會要求輸入客戶的用戶名和密碼,一般在瀏覽器被關閉前或會話超時前,用戶再次訪問時不需再次提供,除非他所請求的操作需要更高的權限??蛻舻挠脩裘兔艽a是通過HTTP的401 Unauthorized響應頭部來激發(fā)客戶端的瀏覽器提示用戶輸入的。
認證通過后,HTTP引擎根據(jù)配置文件的定義給該客戶賦予相應的角色和權限,并設立客戶會話環(huán)境,便于跟蹤客戶的訪問。
當1個HTTP請求被接收后,進入HTTP引擎的處理過程。根據(jù)資源URI判斷,若客戶請求的是靜態(tài)網(wǎng)頁(網(wǎng)頁的后綴是htm或html),那么HTTP引擎在靜態(tài)網(wǎng)頁集中查找,加載到內存,并按照HTTP的協(xié)議規(guī)范封裝響應消息,包括各頭部和協(xié)議實體(響應的數(shù)據(jù)部分)。另外,若本網(wǎng)頁是采用服務器“推”技術的,其頭部信息是不同的,并與客戶端保持永久連接,此后不斷地刷新客戶端的顯示內容。HTTP引擎將封裝好的響應消息返回給客戶端,并刷新緩存。
1.2 分析引擎
分析引擎專注于待分析網(wǎng)頁的分析處理,實現(xiàn)動態(tài)頁面。其實現(xiàn)的傳統(tǒng)技術思路有以下兩種方法[3]:
(1)采用傳統(tǒng)的CGI方式。該方式所需的資源開銷較大,每當用戶請求CGI腳本時,嵌入式Web服務器必須初始化CGI的運行環(huán)境,導入有關參數(shù),然后啟動其他的進程來運行CGI代碼,運行結束后,再釋放進程的相關資源,服務器需要承擔所有額外的負擔,而且和動態(tài)庫的接口也比較麻煩。
(2)使用PHP等腳本語言構建類似主機系統(tǒng)的Web應用服務器。當一個訪問客戶打開網(wǎng)頁時,服務端便執(zhí)行PHP的命令,并將執(zhí)行結果發(fā)送至訪問者的瀏覽器中。該方案與臺式機系統(tǒng)有最好的兼容性,可以充分借鑒和使用臺式機系統(tǒng)的現(xiàn)有軟件和相關源代碼。但是,該方案的實現(xiàn)需要很多資源,需要構建相關的PHP庫,而PHP和嵌入式系統(tǒng)的接口比較困難,因為PHP的設計本身是作為一種服務器端的嵌入式HTML的腳本語言,讓它直接和驅動級的動態(tài)庫等進行鏈接,實現(xiàn)較復雜,特別是不能很好地控制它們之間的交互。而嵌入式系統(tǒng)最需要的是一種實現(xiàn)成本小,而且比較簡單、易于使用、具有相當?shù)撵`活性和可控性,并且和動態(tài)庫有很好的配合機制。
上述兩種方式還有一個共同的缺點,就是實現(xiàn)業(yè)務邏輯的代碼經(jīng)常和網(wǎng)頁的布局代碼交叉在一起,嚴重影響程序的可讀性、可維護性和可擴展性。由于屬于不同層次的代碼混在一起,會使它們的代碼的相關性大大提高,從而極不利于系統(tǒng)的維護。
鑒于上述問題,在嵌入式Web服務器中設計基于嵌入式標記的HTML網(wǎng)頁分析引擎。采用該方法設計的分析引擎的基本特點如下:
(1)視圖(頁面布局)、控制(分析引擎)、模型(接口庫)松耦合。頁面布局和接口庫可以分別獨立地進行設計和開發(fā),前者專注于HTML頁面的布局和美化設計,后者則側重于和控制單元的交互,而分析引擎主要是協(xié)調兩者的工作。通過待分析網(wǎng)頁中的嵌入式標記,關聯(lián)由應用開發(fā)人員編寫動態(tài)庫中的某個函數(shù),以此來動態(tài)生成網(wǎng)頁。
(2)分析引擎中集成了若干應用開發(fā)人員常用的基本功能,如用戶權限管理和口令認證、支持緩存機制、多級客戶授權、一定的安全防范措施等。在此基礎上,應用開發(fā)人員可以只專注于業(yè)務邏輯的處理和調整相關配置,就能構建和靈活調整配置、功能豐富的基于嵌入式Web服務器的系統(tǒng)。
分析引擎和HTTP引擎是通過共享HTTP請求和響應隊列來通信的。在分析引擎的每個運行周期中,進行如下工作:查看HTTP請求隊列是否為空,若有任務則進行分析處理,然后將結果掛入和HTTP引擎共享的響應隊列。分析引擎是周期性運行的,將其掛入運行隊列后,即可處理下個周期的請求。如果循環(huán)1個周期而沒有任務或結果,則進入睡眠。一般分析引擎是單線程,因為在它的運行過程中不大會出現(xiàn)阻塞。此外,作為嵌入式Web服務器,同時訪問量一般不大,即使采用多線程也不大可能顯著地提高系統(tǒng)的性能,而且多線程有更多的開銷。但某些應用可能需要多線程來提高系統(tǒng)的性能。
1.3 嵌入式標記
嵌入式標記的語法是任意連續(xù)的以空格結尾的數(shù)字或字符(除空格和圓括號)序列,設計時采用易于書寫和記憶的簡短的字母數(shù)字序列。共有兩類嵌入式標記在應用開發(fā)人員設計的待分析網(wǎng)頁和靜態(tài)網(wǎng)頁時使用。
(1)參數(shù)替換標記。該類標記用于將傳入的POST等請求的參數(shù)的值直接替換網(wǎng)頁中相應的參數(shù)替換標記。這類標記既是HTTP請求的參數(shù),又可能是結果替換標記的參數(shù)。
(2)結果替換標記。該類標記用于將其代表的代碼段執(zhí)行結果置換網(wǎng)頁中的相應結果替換標記,在置換時可能要進行類型轉換。例如,返回值是整型(int)4 000,引擎會將其轉換成字符串“4 000”,然后替換。
1.4 外部接口庫
外部接口庫是由應用開發(fā)人員提供的用于進行業(yè)務邏輯處理的動態(tài)庫中的某些函數(shù)構成的,這些函數(shù)(稱為外部函數(shù))遵循下面描述的規(guī)則:配置文件中的映射定義部分允許應用開發(fā)人員靈活地將外部函數(shù)的運行特性和與待分析網(wǎng)頁中的結果替換標記的進程對應。分析引擎通過收集的外部函數(shù)的參數(shù)信息和實參值,加載指定的動態(tài)庫,搜索該外部函數(shù)的入口地址,然后構造實際的函數(shù)調用,再采集其返回值,替換相應標記,形成動態(tài)網(wǎng)頁。
這種思路的基本實現(xiàn)技術是動態(tài)裝載。過程如下:分析引擎在第1次調用該動態(tài)庫中的函數(shù)時將其加載(dlopen)到運行進程的地址空間,在庫中查找(dlsym)函數(shù)的地址,然后調用該函數(shù),當不再需要的時候,卸載(dlclose)動態(tài)庫。
在嵌入式Web服務器啟動時,準備了另外的運行線程池,專門用于運行應用開發(fā)任務提供的函數(shù),該線程受嵌入式Web服務器的分析引擎控制。之所以要在另外的線程中運行,是為盡量避免外部函數(shù)代碼對本引擎的影響,可以在出現(xiàn)異常時果斷地終止該運行線程,加上超時定時器,能將外部函數(shù)帶來的風險降低。
運行線程和分析引擎之間通過共享運行隊列和結果隊列來通信。一旦分析引擎有執(zhí)行函數(shù)的需求時,就封裝1個執(zhí)行結構run_struct,它定義了某次HTTP請求所需執(zhí)行的所有函數(shù)及其參數(shù)、運行超時時間等信息,然后將該run_struct掛入運行隊列。運行線程是定期訪問運行隊列的,發(fā)現(xiàn)有任務時,就加載相應的共享庫,查找函數(shù)的入口地址,并加以執(zhí)行,等待其執(zhí)行結束,填充結果,直到run_struct中的所有函數(shù)執(zhí)行完畢(若期間某函數(shù)執(zhí)行異常,有可能導致提前結束),最后將運行完成的run_struct從運行隊列上摘下,掛入結果隊列等待分析引擎的訪問。
運行線程是等待外部函數(shù)執(zhí)行完畢后,再繼續(xù)執(zhí)行的。如果有多個HTTP請求等待處理,而又只有1個運行線程時,可能會有較大的延時,故可根據(jù)具體應用的實際情況,將運行線程的數(shù)量配置成多個。但不可過多,因為線程本身也要占有一定的資源,而線程切換同樣需要開銷。
2 嵌入式Web服務器的設計
嵌入式Web服務器與通用Web服務器比較,存在以下3個方面的差別[4]:
(1)運行的目標環(huán)境不一樣。通用Web服務器一般運行在計算資源和內存資源都比較豐富的臺式機上,而嵌入式Web服務器運行的目標系統(tǒng)大多是各類專用設備,資源比較缺乏。
(2)在各自系統(tǒng)中的作用不一樣。通用Web服務器主要是利用Web服務器向用戶提供信息服務,而嵌入式Web服務器嵌入在設備中,其主要作用是控制和配置設備,但也向客戶提供設備的運行信息。
(3)運行的優(yōu)先級不一樣。嵌入式Web服務器作為一種監(jiān)控、管理手段存在,它不能干擾設備主要任務的運行。
針對于上面嵌入式Web服務器與通用Web服務器的不同,設計嵌入式Web服務器時考慮的性能指標也不一樣。對于嵌入式Web服務器來說,吞吐率并不需要很大,而需要很快的系統(tǒng)響應速度,因為嵌入式Web服務器面對的用戶是少量的設備管理人員,實現(xiàn)的是監(jiān)控與管理功能。一個好的Web服務器應具備良好的可移植性、可裁剪性和與目標設備良好的兼容性。
嵌入式Web服務器中,其Web引擎(HTTP引擎和分析引擎)是核心部分。嵌入式Web引擎的狀態(tài)圖如圖2所示。
圖2中的管理應用是嵌入式Web服務器與應用設備的接口。它用來實現(xiàn)獲取用戶所需的設備信息及執(zhí)行實際的管理設備功能,構成監(jiān)控、管理設備的用戶界面。
有時該用戶界面是靜態(tài)的,但大部分是隨時間動態(tài)改變的。如客戶請求設備狀態(tài)參數(shù)時,嵌入式Web服務器通過調用管理應用程序獲得設備動態(tài)信息,然后組織成動態(tài)Web頁面返回給客戶端;如用戶通過Web頁面發(fā)送1個控制命令字,Web服務器也需通過調用管理應用程序,把該命令相關參數(shù)傳遞給實際執(zhí)行控制動作的管理程序并監(jiān)視其執(zhí)行,把執(zhí)行結果組織成Web頁面的形式返回給用戶。在嵌入式Web服務器中實現(xiàn)應用程序的接口技術有公共網(wǎng)關技術(CGI)和服務器端包含技術(SSI)。
嵌入式系統(tǒng)中,Web服務器作為單獨的任務執(zhí)行,任務的優(yōu)先級應設置成較低的優(yōu)先級,以避免對嵌入式系統(tǒng)主要功能造成干擾。嵌入式Web服務器的結構包括核心部分和可裁剪的功能模塊部分。核心部分包含HTTP請求分析引擎和模塊分析器。HTTP請求分析引擎負責接收客戶端發(fā)送來的HTTP請求報文,獲得客戶端信息,并把解析出的信息保存到請求結構中,后續(xù)處理模塊都從該結構中獲得請求報文的相關信息;模塊分析器則是根據(jù)配置信息調度其他功能模塊。模塊分配器執(zhí)行流程如圖3所示。
RPM(Request Process Module)可以根據(jù)用戶的需求進行裁剪,它分成兩種類型:系統(tǒng)PRM和用戶PRM。一旦配置了系統(tǒng)PRM模塊,則該PRM模塊對服務器接收到的所有請求都會進行處理;用戶PRM模塊則根據(jù)進一步的配置信息,只對某些特定的請求進行處理。
針對嵌入式Web服務器采用以下措施可以提高系統(tǒng)性能:
(1)減小Web服務器中請求的生命周期以縮短等待時間。
(2)在Web服務器中使用線程取代進程來加強系統(tǒng)的并發(fā)性。
(3)采用瘦Web服務器、胖客戶機的應用模式以提升服務性能。
隨著因特網(wǎng)的迅速發(fā)展,需構造嵌入式Web應用系統(tǒng)的應用也越來越多,嵌入式Web服務器將會有很好的發(fā)展前景。
參考文獻
[1] 冀振燕.UML系統(tǒng)分析設計與應用案例[M].北京:人民郵電出版社,2003.
[2] CONALLEN J. Building Web applications with UML. Addison Wesley Longman,2000.
[3] 陳偉,邱書波.蓄電池生產(chǎn)控制網(wǎng)絡結構的設計與實現(xiàn)[J].微計算機信息,2009(1-3).
[4] DOUGLASS B P.實時UML——開發(fā)嵌入式系統(tǒng)高效對象[M].尹浩瓊譯.北京:中國電力出版社,2003.