怎么實現一個網站的Web Serve?Web服務器可以解析(handles)HTTP協(xié)議。當Web服務器接收到一個HTTP請求(request),會返回一個HTTP響應(response),例如送回一個HTML頁面。
怎么實現一個網站的Web Serve?Web服務器可以解析(handles)HTTP協(xié)議。當Web服務器接收到一個HTTP請求(request),會返回一個HTTP響應(response),例如送回一個HTML頁面。
定時器 Timer
如果一個請求在建立連接后遲遲沒有發(fā)送數據,或者對方突然斷電,應該如何處理?我們需要實現定時器來處理超時的請求。Vino 定時器的實現參考了 Nginx 的設計,Nginx 使用一顆紅黑樹來存儲各個定時事件,每次事件循環(huán)時從紅黑樹中不斷找出最小(早)的事件,如果超時則觸發(fā)超時處理。為了簡化實現,在 Vino 中,我實現了一個小頂堆來存儲定時事件,如果被處理的定時事件同時支持長連接,那么在該請求處理完畢后會更新該請求對應的定時器,也就是重新計時。定時器相關代碼見 vn_event_timer.h 和 vn_event_timer.c。
HTTP Parser
由于網絡的不確定性,我們并不能保證一次就能讀取所有的請求數據。因此,對于每一個請求,我們都會開辟一段緩沖區(qū)用于保存已經讀取到的數據。同時,我們需要同時對讀取到的數據進行解析,以保證讀取到的數據都是合理的數據,例如,假設目前緩沖區(qū)內的數據為 GET /index.
html HTT,那么下一次讀取到的字符必須為 P,否則,應立即檢測出當前請求是一個異常的請求,并主動關閉當前的連接。
基于以上分析,我們需要實現一個 HTTP 狀態(tài)機(Parser)來維持當前的解析狀態(tài),Vino 狀態(tài)機的實現參考了 Nginx 的設計,并對 Nginx 的實現做了簡化。HTTP Parser 相關代碼見 vn_
http_parse.h 和 vn_http_parse.c。
Memory Pool
我們一般使用 malloc/calloc/free 來分配/釋放內存,但是這些函數對于一些需要長時間運行的程序來說會有一些弊端。頻繁使用這些函數分配和釋放內存,會導致內存碎片,不容易讓系統(tǒng)直接回收內存。典型的例子就是大并發(fā)頻繁分配和回收內存,會導致進程的內存產生碎片,并且不會立馬被系統(tǒng)回收。
使用內存池分配內存,可以在一定程度上提升內存分配的效率,不需要每次都調用 malloc/calloc 函數。同時,使用內存池使得內存管理更加簡單。在 Vino 中,針對每一個請求,Vino 都會為其分配一或多個內存池(各個內存池形成一個單鏈表),在請求處理完畢后,一并釋放所有的內存。
Vino 內存池的實現依舊參考了 Nginx 的實現,并做了簡化,Memory Pool 相關代碼見 vn_palloc.h 和 vn_palloc.c。
其他
在開發(fā) Vino 的過程中,還有許多需要考慮和權衡的地方。響應請求時,如果用戶請求的是一個很大的文件,導致寫緩沖區(qū)滿,我們如何更好的設計響應緩沖區(qū)?如何更高效的設計底層數據結構(如字符串、鏈表、小頂堆等)?如何更優(yōu)雅的解析命令行參數?如何對特定信號進行處理?如何更健壯的處理錯誤信息?當代碼的數量達到一定程度后,如何更快的定位異常代碼?
Vino 的開發(fā) & 重構暫時告一段落,源碼放在了 GitHub 上。當然,Vino 還有許多不足之處,以及未實現的特性。
僅支持 HTTP GET 方法,暫不支持其他 HTTP method。
暫不支持動態(tài)請求的處理。
支持的 HTTP/1.1 特性有限。
以上就是小編對于怎么實現
一個網站的Web Serve的全部解答。