江存
基于Linux的2種HTTP服務(wù)器實現(xiàn)與對比分析
江存
(四川大學(xué)計算學(xué)院,成都 610000)
探討Linux環(huán)境下的多線程并發(fā)編程的問題,介紹采用C語言實現(xiàn)基于動態(tài)線程池模式的簡單服務(wù)器與基于epoll+多線程模式的簡單服務(wù)器,采用Webbench進行壓力測試,并對結(jié)果做出分析與思考。
線程池;epoll;并發(fā)編程;HTTP
HTTP協(xié)議是互聯(lián)網(wǎng)中重要的協(xié)議,Web瀏覽器、服務(wù)器和相關(guān)的應(yīng)用程序都是HTTP互通的,對其進行研究十分有必要。本文著重研究分析了HTTP服務(wù)器的設(shè)計與實現(xiàn)方式,一個設(shè)計架構(gòu)良好的服務(wù)器需要高效穩(wěn)定可擴展性,盡可能滿足多的任務(wù)請求。本文著重設(shè)計實現(xiàn)了態(tài)線程池模式和epoll加多線程模式,并對其進行分析。
1.1 HTTP協(xié)議簡介
http服務(wù)器是基于TCP協(xié)議的應(yīng)用層協(xié)議,名為超文本傳輸協(xié)議。Web客戶端與服務(wù)器端進行數(shù)據(jù)傳輸就是依靠HTTP協(xié)議實現(xiàn)的。它是全球因特網(wǎng)使用的公共語言。
通常,一個客戶端與服務(wù)器建立連接之后,會發(fā)送一個請求個服務(wù)器,請求報文的格式一般為:請求起始行、請求首部字段和主體部分。服務(wù)器在將報文解析出來,在發(fā)送一個響應(yīng)報文,和請求報文類似,也分為三個部分:響應(yīng)起始行、響應(yīng)首部、響應(yīng)主體。
請求報文格式如下:
<method> <reque-uri> <version>
<headers>
<entity-body>
響應(yīng)報文格式為:
<version> <status> <reason-pharse>
<headers>
<entity-body>
●方法(method)
客戶希望服務(wù)器對資源進行的動作。如get,post等方法。
●請求 URL(request-URL)
所請求的資源地址。
●版本(version)
所使用的HTTP協(xié)議版本。
●狀態(tài)碼(status)
這三位數(shù)字描述了請求過程中所發(fā)生的情況。
●原因短語(reason-phrase)
數(shù)字狀態(tài)碼的可讀版本,包含行終止序列的所有文本。
●首部(header)
可以有零個或者多個首部,每個首部包含一個名字,后面接一個逗號,然后是個可選空格,然后是一個值,最后是一個CRLF。
●實體的主體部分(entity-body)
包含任意數(shù)據(jù)組成的數(shù)據(jù)塊。并不是所有的報文都包含實體的主體部分,有時報文以一個CRCL結(jié)束。
1.2 HTTP服務(wù)器架構(gòu)分析與設(shè)計
(1)基于線程池的HTTP服務(wù)器
由于單個進程無法同時處理讀個連接,并且無法發(fā)揮服務(wù)器多核心的優(yōu)勢,但是用多進程,每個進程分別處理不同的請求,又太耗費資源,所以采用多線程的模型來處理,與此同時,由于HTTP請求和響應(yīng)很快,創(chuàng)建和銷毀線程又非常的頻繁,需要很大的系統(tǒng)資源開銷,所以采用預(yù)先創(chuàng)建線程池來處理HTTP任務(wù),既發(fā)揮了CPU多核心的優(yōu)勢又減少了不必要的系統(tǒng)開銷。服務(wù)器工作原理如下:首先建立套接字描述符,接著綁定地址,在監(jiān)聽套接字看是否有連接接入,有接入就分配一個線程去處理任務(wù)。
其中線程池管理過程為:當(dāng)主線程獲取了一個連接后,將任務(wù)添加到線程池管理結(jié)構(gòu)中的任務(wù)隊列中,并檢測是否需要增加線程,喚醒等待中的線程,喚醒的線程去任務(wù)隊列中取下任務(wù)進行處理,處理完后繼續(xù)隊列任務(wù)。如此同時,單獨創(chuàng)建一個檢測線程,當(dāng)滿足條件后就會銷毀一部分線程,以達到根據(jù)具體需求動態(tài)改變線程池大小的需求,如此往復(fù)。
(2)基于epoll加多線程的HTTP服務(wù)器架構(gòu)
由于前面采用線程池模型,每個請求必須要一個線程去處理,處理完成后才會去做下一個任務(wù),如果請求時保持型的長連接,那么很快線程池就被消耗完了,而其他的請求得不到滿足。在這個問題基礎(chǔ)上,改進了單獨線程池模型的不足,采用epoll模型來,為了充分利用多核心的優(yōu)勢,采用了多線程加epoll模型,每個線程單獨處理一個epoll對象,這樣線程之間互不干擾,減少線程調(diào)度和切換的開銷,同時提高了CPU的利用率。
2.1 線程池模型關(guān)鍵結(jié)構(gòu)設(shè)計
(1)下面介紹一些必要的數(shù)據(jù)結(jié)構(gòu)
●任務(wù)結(jié)點設(shè)計
(2)服務(wù)器處理步驟
圖1
圖2
2.2 epoll+多線程模式關(guān)鍵結(jié)構(gòu)設(shè)計
(1)epoll主要結(jié)構(gòu)如下
①連接信息結(jié)構(gòu)
void add_epoll_event(int epfd,Conn*conn,int flags)函數(shù)負責(zé)向epoll對象中添加事件信息,epfd是epoll對象文件描述符,conn是連接請求信息,flags事件觸發(fā)方式。
void mod_epoll_event(int epfd,Conn*conn,int flags)函數(shù)負責(zé)對epoll對象中的事件信息進行修改。
void del_epoll_event_close_fd(int epfd,Conn*conn)函數(shù)負責(zé)刪除epoll對象中的事件,并且關(guān)閉套接字描述符fd。
其他創(chuàng)建和收集發(fā)生事件的連接直接調(diào)用系統(tǒng)函數(shù)epoll_create和epoll_wait函數(shù)。
(2)基于epoll的服務(wù)器處理流程圖如下:
圖3
筆者采用開源軟件Webbench進行測試,主要采用GET方法請求,屬于I/O型事件處理請求,兩個模式服務(wù)器部署在同一個主機上進行測試,另一個主機每次模擬不同數(shù)量的客戶端,每次測試時間30秒,測試10次,失敗為止,表1是基于線程池的服務(wù)器的測試數(shù)據(jù),表2是基于epoll+多線程的服務(wù)器的測試數(shù)據(jù),可以看到,隨著并發(fā)客戶數(shù)越多,epoll效率幾乎不受影響,同等條件下,當(dāng)并發(fā)數(shù)超過4000時,線程池服務(wù)器就會出現(xiàn)請求失敗的情況,而epoll服務(wù)器幾乎不受影響。說明對于高并發(fā)和I/O型事件,epoll模式要由于一般的線程池模式。測試結(jié)果如下:
基于線程池服務(wù)器測試的截圖和結(jié)果:
圖4
圖5
筆者研究了HTTP服務(wù)器原理以及實現(xiàn),并且為了最大可能利用計算機資源和盡可能并發(fā)處理程序,經(jīng)過比較最后選擇基于線程池和epoll+線程模式兩種方式進行對比測試分析,得出在不同情況下根據(jù)具體需求采用不同模型的必要性,當(dāng)并發(fā)程度要求不高,二者性能將近,但是特別是在并發(fā)連接多I/O型事件請求任務(wù)下,epoll模式表現(xiàn)良好。一個好的服務(wù)器需要考慮很多方面,筆者才疏學(xué)淺只是在相對理想條件下進行測試,總之對此還需繼續(xù)深入的研究與分析。
表1
表2
[1]W.Richard Stevens,Stephen A.Rago著.UNIX環(huán)境高級編程[M].戚正偉,張亞英,尤晉元譯.北京:人民郵電出版社,2014.
[2]W.Richard Stevens,Bill Fenner,Andrew M.Ruoff著.UNIX網(wǎng)絡(luò)編程[M].北京:人民郵電出版社,2015.
[3]David Gourley,Brian Totty,Marjorie Sayer,Sailu Reddy,Anshu Aggarwal著.HTTP權(quán)威指南[M].陳涓,趙振平譯.北京:人民郵電出版社,2012.
[4]王遠洋,周淵平,郭煥麗.Linux下基于Socket多線程并發(fā)通信的實現(xiàn)[J].微計算機信息,2009,25(5).
[5]催濱,萬旺根,余小清,樓順天.基于EPOLL機制的Linux網(wǎng)絡(luò)游戲服務(wù)器實現(xiàn)方法[J].微計算機信息,2006,22(7).
[6]梁明剛,陳西曲.Linux下基于epoll+線程池高并發(fā)服務(wù)器實現(xiàn)研究[J].武漢輕工大學(xué)學(xué)報,2012,31(3).
Implementation and Comparison of Two Kinds of HTTP Server Based on Linux
JIANG Cun
(College of Computer Science,Sichuan University,Chengdu 610000)
Discusses the problem of multi-threaded concurrent programming in Linux environment,introduces the simple server based on dynamic thread pool mode and simple server based on epoll+multi-thread mode written in C language and Webbench is used for stress testing,fi?nally makes a summary of test.
Thread Pool;Epoll;Concurrent Programming;HTTP
1007-1423(2017)24-0058-05
10.3969/j.issn.1007-1423.2017.24.014
江存(1991-),男,湖北黃岡人,碩士研究生,研究方向為網(wǎng)絡(luò)與信息安全
2017-04-27
2017-08-05