高效能伺服器程式設計之epoll

2021-08-11 15:29:34 字數 2409 閱讀 5613

在linux的網路程式設計中,經常使用多執行緒處理高併發的問題,然而linux系統對執行緒數量是有限制的,更重要的是執行緒的排程有系統開銷的,在客戶端數量龐大時,這將是無法接受的問題;另一種處理高併發的方法是使用select來做事件觸發,select實現中,它是採用輪詢來處理的,輪詢的fd數目越多,耗時越多,而且,在linux/posix_types.h標頭檔案有這樣的宣告:

#define __fd_setsize    1024

表示select最多同時監聽1024個fd,當然,可以通過修改標頭檔案再重編譯核心來擴大這個數目,但這並不是很好的解決辦法。

為了解決這一問題,linux核心為處理大批量檔案描述符而作了改進的poll,是linux下多路復用io介面select/poll的增強版本,它能顯著提高程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率;獲取事件的時候,它無須遍歷整個被偵聽的描述符集,只要遍歷那些被核心io事件非同步喚醒而加入ready佇列的描述符集合就行了。epoll提供了水平觸發(leveltriggered)和邊緣觸發(edgetriggered)兩種模式,具體在後續介紹。

epoll的介面非常簡單,一共就三個函式:

1. int epoll_create(int size);

建立乙個epoll的控制代碼,size用來告訴核心這個監聽的數目一共有多大。需要注意的是epoll也是乙個控制代碼,不再使用時需要主動呼叫close關閉,否則會導致控制代碼資源洩露。

2. int epoll_ctl(int epfd, int op, int fd,struct epoll_event *event);

epoll的事件註冊函式

第乙個引數是epoll控制代碼,epoll_create()的返回值;

第二個引數表示動作,用三個巨集來表示:

epoll_ctl_add:註冊新的fd到epfd中;

epoll_ctl_mod:修改已經註冊的fd的監聽事件;

epoll_ctl_del:從epfd中刪除乙個fd;

第三個引數是需要監聽的fd;

第四個引數是監聽的事件,用structepoll_event結構表示,具體如下:

typedef union epoll_data  epoll_data_t;

struct epoll_event ;

events可以是以下幾個巨集的集合:

epollin :表示對應的檔案描述符可以讀(包括對端socket正常關閉);

epollout:表示對應的檔案描述符可以寫;

epollpri:表示對應的檔案描述符有緊急的資料可讀(這裡應該表示有帶外資料到來);

epollerr:表示對應的檔案描述符發生錯誤;

epollhup:表示對應的檔案描述符被結束通話;

epollet: 將epoll設為邊緣觸發(edge triggered)模式,這是相對於水平觸發(level triggered)來說的。

epolloneshot:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到epoll佇列裡

3. int epoll_wait(int epfd, structepoll_event * events, int maxevents, int timeout);

等待事件的產生,類似於select()呼叫。引數events用來從核心得到事件的集合,maxevents告之核心這個events有多大,這個 maxevents的值不能大於建立epoll_create()時的size,引數timeout是超時時間(毫秒,0會立即返回,-1將不確定,也有說法說是永久阻塞)。該函式返回需要處理的事件數目,如返回0表示已超時。

關於水平觸發(leveltriggered)和邊緣觸發(edgetriggered)兩種模式;水平觸發模型下只要緩衝區有資料就會不斷獲得通知;邊緣觸發模式僅當狀態發生變化的時候才獲得通知,可以理解為緩衝區由0變為1或者由1變為0時才會獲得通知。水平觸發事件不會丟棄,而邊緣觸發處理更高效。

1.盡量使用分布式、去中心化、無狀態化、一致性雜湊等;

2.盡量少的執行緒切換,盡量少的共享衝突,盡量無鎖;

3.盡量沒有等待時間片的執行緒,邏輯盡量簡化,避免不必要的封裝和**;

4.不要在epoll_wait()執行緒中用太長時間處理非epoll_wait()的事情;

5.能用atomic的就不要用mutex;

6.資料庫盡量採用分布式,採用好的資料路由中間層服務,好的集群管理器資料庫,盡量分庫分表,建議使用hash分表,盡量避免按區段分表。

7.如果非要有中心,請盡量選摺以下兩個方案:

a. 中心如果很簡單,請確保在崩潰/殺死後,1秒鐘內能立刻復活啟動~~~

b. 中心改為管理集群,自動選舉主核心。當原主核心失效後,新的核心自動接管當前集群網路。

8.不要使用xml,如果文字,使用json。如果二進位制,請使用json對應的二進位製化協議。

高效能伺服器之epoll

什麼是epoll epoll是什麼?是為處理 大批量控制代碼 而作了改進的poll。它 幾乎具備了之前所說的 一切優點,被公認為linux2.6下效能最好的多路i o就緒通 知 方法。epoll的相關系統調 用 epoll只有epoll create,epoll ctl,epoll wait 3個系...

高效能伺服器程式設計感悟

前些年,程式效能隨著硬體公升級而提公升往往不怎麼需要程式設計師的參與。比如cpu頻率從100m上公升到500m,原先要執行1min的程式現在可能只要執行10幾秒。而需要使用大記憶體的程式在記憶體擴容後執行速度也往往可以提高很多。但是現在情況發生了變化,想想吧。主流配置為cpu主頻2g 記憶體2g的時...

linux高效能伺服器程式設計

linux高效能伺服器程式設計 當當網 亞馬遜 目錄 第一章 tcp ip協議族 第二章 ip協議族 第三章 tcp協議詳解 第四章 tcp ip通訊案例 訪問internet 第五章 linux網路程式設計基礎api 第六章 高階io函式 第七章 linux伺服器程式規範 第八章 高效能伺服器框架...