您當前位置>首頁 » 新聞資(zī)訊 » 網站(zhàn)建設 >
C++web服務器(qì)開發
發表時間:2019-8-14
發布人:葵宇科技
浏覽次數:47
C++web服務器(qì)開發
1. 首先介紹一下(xià)這個(gè)項目;這個(gè)項目是通(tōng)過C++11編寫的web服務器(qì),模型為Reactor+非阻塞I/O(epoll作為I/O多路(lù)複用實現方式)+線程池,支持get、head請求,支持HTTP長連接,并實現了優雅關(guān)閉連接。
I/O多路(lù)複用是什麼技術(shù)呢(ne)? I/O多路(lù)複用(multiplexing)的本質是通(tōng)過一種機制(系統内核緩沖I/O數據),讓單個(gè)進程可(kě)以監視多個(gè)文(wén)件描述符,一旦某個(gè)描述符就緒(一般是讀就緒或寫就緒),能夠通(tōng)知程序進行相應的讀寫操作。(包括select、poll、epoll)
文(wén)件描述符 文(wén)件描述符(File descriptor)是計算機科學中(zhōng)的一個(gè)術(shù)語,是一個(gè)用于表述指向文(wén)件的引用的抽象化概念。
文(wén)件描述符在形式上是一個(gè)非負整數。實際上,它是一個(gè)索引值,指向内核為每一個(gè)進程所維護的該進程打開文(wén)件的記錄表。當程序打開一個(gè)現有文(wén)件或者創建一個(gè)新文(wén)件時,内核向進程返回一個(gè)文(wén)件描述符。在程序設計中(zhōng),一些涉及底層的程序編寫往往會圍繞着文(wén)件描述符展開。但是文(wén)件描述符這一概念往往隻适用于UNIX、Linux這樣的操作系統。
select、poll和(hé)epoll的區别 select函數隻能輪詢linux操作系統提供的fd_set這個(gè)類型的變量,poll函數輪詢的是pollfd這個(gè)類型的數組,這個(gè)數組可(kě)以自己定義長度,而不是上面select函數隻能輪詢定長為FD_SETSIZE的fd_set變量。epoll不再是輪詢,而是給每個(gè)文(wén)件描述符上發生的io事件設置一個(gè)回調函數。
2.定時器(qì)是怎麼實現的?還有什麼實現方式?
定時器(qì)用來處理超時的請求和(hé)長時間不活躍的連接,使用stl裡的priority_queue,基于小根堆的定時器(qì)關(guān)閉超時請求,并采用惰性删除的方式,時間的到來不會喚醒線程,而是每次循環的最後進行檢查,如(rú)果超時了再删,因為這裡對超時的要求并不會很高,如(rú)果此時線程忙,那麼檢查時間隊列的間隔也會短(duǎn),如(rú)果不忙,也給了超時請求更長的等待時間。還可(kě)以使用STL中(zhōng)的set。
3.實現一個(gè)無鎖隊列? 用原子(zǐ)操作
4.eventfd是什麼?有什麼好處?
eventfd是系統提供的一個(gè)輕量級的進程間通(tōng)信的系統調用,eventfd實現了線程的異步喚醒(eventfd()會返回一個(gè)文(wén)件描述符,如(rú)果該進程被fork的時候,這個(gè)文(wén)件描述符也會複制過去,這時候就會有多個(gè)的文(wén)件描述符指向同一個(gè)eventfd對象)
5.雙緩沖區異步日志是什麼?為什麼要這樣做?對這個(gè)日志系統有沒有進行壓力測試?
基本思路(lù)是準備兩塊buffer:A和(hé)B, 前端負責往buffer A填數據(日志消息), 後端負責将buffer B的數據寫入文(wén)件;當buffer A寫滿之後, 交換A和(hé)B, 讓後端将buffer A的數據寫入文(wén)件, 而前端則往buffer B填入新的日志消息, 如(rú)此往複。
好處:前端不是将一條條日志消息分别送給後端,而是将多條日志消息拼接成一個(gè)大的buffer傳送給後端,相當于批處理,減少(shǎo)了線程喚醒的開銷。
6.什麼是優雅關(guān)閉連接?
就是read()到0,要透明的傳遞這個(gè)行為而不是直接暴力close()
7.epoll的邊沿觸發(et)和(hé)水平觸發(lt)有什麼區别? lt模式下(xià),默認不可(kě)讀,隻有epoll通(tōng)知你(nǐ)可(kě)讀才是可(kě)讀,否則不可(kě)讀。
et模式下(xià),默認可(kě)讀。你(nǐ)可(kě)以随便讀,直到發生EAGAIN。可(kě)讀時讀和(hé)不讀,怎麼讀都由你(nǐ)自己決定,中(zhōng)間epoll不管。
EAGAIN後不可(kě)讀了,等到再次可(kě)讀,epoll會再通(tōng)知一次。
ET模式要比LE複雜許多,它對用戶提出了更高的要求,即每次讀,必須讀到不能再讀(出現EAGAIN),每次寫,寫到不能再寫(出現EAGAIN)。而LT則簡單的多,可(kě)以選擇也這樣做,也可(kě)以為編程方便,比如(rú)每次隻read一次(muduo就是這樣做的,這樣可(kě)以減少(shǎo)系統調用次數)。
8.epoll為什麼高效,相比select和(hé)poll
- 減少(shǎo)了用戶态和(hé)内核态之間的文(wén)件描述符拷貝
- 減少(shǎo)了對就緒文(wén)件描述符的遍曆
9.假如(rú)服務器(qì)要升級,又不想讓用戶感覺到服務器(qì)升級了,該怎麼做?
不間斷的提供服務,參考nginx的平滑升級
10.Reactor模式是什麼?
反應器(qì)設計模式(Reactor pattern)是一種為處理并發服務請求,并将請求提交到一個(gè)或
者多個(gè)服務處理程序的事件設計模式。當客戶端請求抵達後,服務處理程序使用多路(lù)分配策略,由一個(gè)非阻塞的線程來接收所有的請求,然後派發這些請求至相關(guān)的工作線程進行處理。