單線程 Non-Blocking

  Vino 整體采用了基于事件驅動的單線程 Non-Blocking 模型。采用單線程模型,避免了系統分配多線程及線程之間通信的開銷,同時降低了內存的耗用。由于采用了單線程模型,為了更好的提高線程利用率,Vino 將默認 Blocking 的 I/O 設置為 Non-Blocking I/O,即在線程讀/寫數據的過程中,如果緩沖區為空/緩沖區滿,線程不會阻塞,而是立即返回,并設置 errno。

  Vino 最初的靈感來源于 Computer Systems: A Programmer\\\’s Perspective 一書講述網絡編程時實現的一個簡單的 Web Server,每到來一個請求,Web Server 都會 fork 一個進程去處理。顯然,在高并發的場景下,這種模型是不合理的。每次 fork 進程會帶來巨大的開銷,并且系統中進程的數量是有限的。同時,伴隨多進程帶來的進程調度的開銷也不可小覷,CPU 會花費大量的時間用于決定調用哪一個進程。進程調度引發的進程上下文之間的切換,也需要耗費相當大的資源。

  很容易聯想到采用多線程模型來替代多進程模型,相比于多進程模型,多線程模型占用的系統資源會大大降低,但是本質上并沒有減小線程調度帶來的開銷。為了減小由線程調度導致的開銷,我們可以采用線程池模型,即固定線程的數量,但是問題依舊存在:因為 Linux 默認 I/O 是阻塞(Blocking)的,如果線程池中所有的線程同時阻塞于正在處理的請求,那么新到來的請求就沒有線程去處理了。因此,如果我們用 Non-Blocking 的 I/O 替換默認的 Blocking I/O,線程將不會阻塞于數據的讀寫,問題便可得到解決。

  HTTP Keep-Alive

  Vino 支持 HTTP 長連接(Persistent Connections),即多個請求可以復用同一個 TCP 連接,以此減少由 TCP 建立/斷開連接所帶來的性能開銷。每到來一個請求,Vino 會對請求進行解析,判斷請求頭中是否存在 Connection: keep-alive 請求頭。如果存在,在處理完一個請求后會保持連接,并對數據緩沖區(用于保存請求內容,響應內容)及狀態標記進行重置,否則,關閉連接。

  關于 HTTP Keep-Alive 的優勢,RFC 2616 有著更完善的總結,引用如下。

  By opening and closing fewer TCP connections, CPU time is saved in routers and hosts (clients, servers, proxies, gateways, tunnels, or caches), and memory used for TCP protocol control blocks can be saved in hosts.

  HTTP requests and responses can be pipelined on a connection. Pipelining allows a client to make multiple requests without waiting for each response, allowing a single TCP connection to be used much more efficiently, with much lower elapsed time.

  Network congestion is reduced by reducing the number of packets caused by TCP opens, and by allowing TCP sufficient time to determine the congestion state of the network.

  Latency on subsequent requests is reduced since there is no time spent in TCP\\\’s connection opening handshake.

  HTTP can evolve more gracefully, since errors can be reported without the penalty of closing the TCP connection. Clients using future versions of HTTP might optimistically try a new feature, but if communicating with an older server, retry with old semantics after an error is reported.

  定時器 Timer

  如果一個請求在建立連接后遲遲沒有發送數據,或者對方突然斷電,應該如何處理?我們需要實現定時器來處理超時的請求。Vino 定時器的實現參考了 Nginx 的設計,Nginx 使用一顆紅黑樹來存儲各個定時事件,每次事件循環時從紅黑樹中不斷找出最小(早)的事件,如果超時則觸發超時處理。為了簡化實現,在 Vino 中,我實現了一個小頂堆來存儲定時事件,如果被處理的定時事件同時支持長連接,那么在該請求處理完畢后會更新該請求對應的定時器,也就是重新計時。定時器相關代碼見 vn_event_timer.h 和 vn_event_timer.c。

  HTTP Parser

  由于網絡的不確定性,我們并不能保證一次就能讀取所有的請求數據。因此,對于每一個請求,我們都會開辟一段緩沖區用于保存已經讀取到的數據。同時,我們需要同時對讀取到的數據進行解析,以保證讀取到的數據都是合理的數據,例如,假設目前緩沖區內的數據為 GET /index.html HTT,那么下一次讀取到的字符必須為 P,否則,應立即檢測出當前請求是一個異常的請求,并主動關閉當前的連接。

  基于以上分析,我們需要實現一個 HTTP 狀態機(Parser)來維持當前的解析狀態,Vino 狀態機的實現參考了 Nginx 的設計,并對 Nginx 的實現做了簡化。HTTP Parser 相關代碼見 vn_http_parse.h 和 vn_http_parse.c。

  Memory Pool

  我們一般使用 malloc/calloc/free 來分配/釋放內存,但是這些函數對于一些需要長時間運行的程序來說會有一些弊端。頻繁使用這些函數分配和釋放內存,會導致內存碎片,不容易讓系統直接回收內存。典型的例子就是大并發頻繁分配和回收內存,會導致進程的內存產生碎片,并且不會立馬被系統回收。

  使用內存池分配內存,可以在一定程度上提升內存分配的效率,不需要每次都調用 malloc/calloc 函數。同時,使用內存池使得內存管理更加簡單。在 Vino 中,針對每一個請求,Vino 都會為其分配一或多個內存池(各個內存池形成一個單鏈表),在請求處理完畢后,一并釋放所有的內存。

  Vino 內存池的實現依舊參考了 Nginx 的實現,并做了簡化,Memory Pool 相關代碼見 vn_palloc.h 和 vn_palloc.c。

  其他

  在開發 Vino 的過程中,還有許多需要考慮和權衡的地方。響應請求時,如果用戶請求的是一個很大的文件,導致寫緩沖區滿,我們如何更好的設計響應緩沖區?如何更高效的設計底層數據結構(如字符串、鏈表、小頂堆等)?如何更優雅的解析命令行參數?如何對特定信號進行處理?如何更健壯的處理錯誤信息?當代碼的數量達到一定程度后,如何更快的定位異常代碼?

  Vino 的開發 & 重構暫時告一段落,源碼放在了 GitHub 上。當然,Vino 還有許多不足之處,以及未實現的特性。

  僅支持 HTTP GET 方法,暫不支持其他 HTTP method。

  暫不支持動態請求的處理。

  支持的 HTTP/1.1 特性有限。

  …

  寫這篇文章,希望對初學者有所幫助。

更多關于云服務器域名注冊,虛擬主機的問題,請訪問三五互聯官網:m.shinetop.cn

贊(0)
聲明:本網站發布的內容(圖片、視頻和文字)以原創、轉載和分享網絡內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。郵箱:3140448839@qq.com。本站原創內容未經允許不得轉載,或轉載時需注明出處:三五互聯知識庫 » 怎么去實現一個Web Server

登錄

找回密碼

注冊

主站蜘蛛池模板: 97人妻成人免费视频| 尚义县| 在线播放国产精品一品道| 91中文字幕一区在线| 国产日韩av二区三区| 日韩在线观看 一区二区| 好深好湿好硬顶到了好爽| 丁香五月亚洲综合在线国内自拍| 国产超碰人人做人人爰| 午夜福利一区二区三区在线观看| 最新的国产成人精品2022| 成人拍拍拍无遮挡免费视频| 一卡2卡三卡4卡免费网站| 色窝窝免费播放视频在线| 999福利激情视频| 亚洲精品理论电影在线观看| 国产精品伦人一久二久三久| 国产成人精品午夜2022| 熟妇激情一区二区三区| 国产精品中文字幕日韩| 欧美性xxxxx极品| 日韩久久久久久中文人妻| 亚洲一区二区三区18禁| 狂躁女人双腿流白色液体| 国产欧美日韩高清在线不卡| 国产午夜成人久久无码一区二区| 日本亚洲一区二区精品久久| 免费AV手机在线观看片| 萝北县| 亚洲男人第一无码av网| 色综合天天综合天天更新| gogogo高清在线观看视频中文| av天堂午夜精品一区| 人妻精品动漫H无码中字| 福利一区二区在线观看| 蜜桃av无码免费看永久| 黑人巨大无码中文字幕无码| 特级做a爰片毛片免费看无码| 色成人亚洲| 无码专区一va亚洲v专区在线| 国产精品亚洲а∨天堂2021|