從一個嵌入式網絡服務器想到的


首先感激陳碩大大,附鏈接 陳碩的CSDN。《UNP》這本書肯定也是必須的,豆瓣的評價

       最近項目需要有一個嵌入式網絡服務器,在系統中,該模塊需要與每個客戶端保持多個socket連接,然后將收到的數據分別轉發給對應的上層處理模塊。有點像雲風的blog中提到的游戲服務端的接入服務器。但為了滿足實時性,轉發機制不經過socket,直接保存到優先級隊列中。這里面的優化的地方頗多,暫時有零拷貝機制優化,相對於linux中用戶態和內核態的各種緩沖拷貝,VxWorks直接在內核態操作無疑給這方面的優化工作大大的便利,也不准備使用RTP用戶態機制給自己添堵了。這篇博客不准備在這方面寫更多,其實重點是網絡編程模型的一些東西。

       之前一直對linux網絡編程有些感覺,在VxWorks上面,同樣的需求讓我很是驚喜。該模塊大體情況為:使用VxWorks SMP中的CPU親和機制,給該模塊分配一個CPU核單獨使用。每個客戶端會和服務器保持多個連接,各個連接發送不同功能的信息,這些信息將會分配到不同的消息隊列供上層處理。首先想到的是以下三個架構方法:

單任務設計肯定很簡單,連任務切換都省了。在任務中使用select()監聽多個socket,這是《UNP》一書中詳細講解的方法,但對后續優化肯定不方便,而且select那令人dt的輪詢機制和socket連接數限制也會讓人無比羡慕epoll這種大殺器。

要與零拷貝機制結合,最初的設想是多個任務分別監聽,只要注意好驚群效應和任務均衡就ok。這也是《UNP》的設想,比單一任務accept再分發連接效率高。但這么做對后續數據的分發及其不方便,每一個任務都要去判別分發到哪個消息隊列。

那么,單一任務accept。判斷是何種消息socket,再分別發送到各個單一功能任務中。無疑是很好的辦法了。這么做的好處還有一點就是,每個任務都只操作一個消息隊列(只收發一種消息),在零拷貝機制上,可以最大限度地減少拷貝甚至不拷貝。

     第一個方法肯定不用,第二個方法也有改進的地方,多任務accept的時候,可以監聽不同的端口,達到分發效果。這么做有另外的消耗,最重要的是,降低了客戶端的可復用性。可能后續有一些折中,具體選用還得考慮。這些所有的模型,都使用了事件循環機制,每個事件循環可以處理一定量的accept事件和數據I/O事件。

     前幾天參加風河開發者大會,提到物聯網與大數據。無疑,大數據處理在現今是一個很時髦的話題。額,暫時我也沒那范去搞這方面的內容,只是在看面試集錦中,總結起來,大量數據的處理,bit-map、分治法、哈希大致應該為大殺器,理解了就可以秒殺這方面的面試了。

     網絡編程中,處理大量並發連接,何嘗不是一種大數據呢。bit-map和哈希就不去想它了。這里主要想說的是分治法:

把一個復雜的問題分成多個的相同或相似的子問題求解,原問題的解即子問題的解的合並。

     服務器要處理的事情,歸結起來,有三部分:accept、數據IO、數據處理。

     首先感謝epoll機制的高效性。以前的poll機制,有兩個性能瓶頸,一是每次poll都要把需要等待的fd拷貝到內核;二是輪詢。epoll則讓內核保存fd來避免拷貝,以異步回調來處理事件發生。在使用時,可以把epoll看做一個數據處理工具,這個工具有自己的性能瓶頸,處理的數據量是有限制的。那么,怎么去處理超過其瓶頸的數據呢。無疑是分治法:

     將需要處理的“數據”(也可以成為事件)划分給多個epoll事件循環,這些循環交給多線程/多進程去承載。

     首先,Accept和數據IO具有連續性,你可以簡單地使用多個事件循環去accept,每個事件循環處理自己連接上的數據IO。至於數據處理部分,若處理量大,一般使用線程池或者進程池處理。這個方法與UNP一書中多進程/線程Accept有異曲同工之妙,只是將每個進程/線程上的阻塞模型改為事件循環+異步非阻塞模型而已。當然,同時需要處理的還有驚群效應和負載均衡。Nginx是使用該模型的很好的例子。需要注意到的是,每個線程/進程最好只承載一個事件循環。進程/線程數量的安排也與CPU核的個數有關。SMP機制雖然可以讓我們很容易使用多核CPU,但進程/線程在CPU間的轉移有很大的效率上的損失,不論是VxWorks還是linux,都提供進程與CPU核的親緣性與綁定機制,對效率上的增加有一定好處。

    其次,當Acccpt事件和IO事件不對等的時候。例如,一些應用場合Accept事件很少,甚至只是簡單的接受固定的長連接事件(比如上面講的那個嵌入式服務器),但數據IO卻非常多。那么,可以再一個事件循環中專門處理Accept事件,然后將連接分發到專用IO處理事件循環中。數據處理同上一種情況,以計算量大小決定是否選擇pool解決。

   但寫起來,總感覺實際應用情況要復雜得多。不同的數據類型,不同的應用場合,可能在模型設計與性能優化之間有很大折中,可能在網絡服務器這塊選用不是效率最高的那種,但整體考慮,它可能是最適合系統整體優化的。

   項目中要用到SCTP,看來得重回UNP閱讀SCTP部分了。這本書乍一看有些老了。各種編程模型在工業場合也基本不會用,但總感覺那些東西像形狀不同的積木,不論是什么高級的模型,都可以再這里找到原型。OK。繼續看書吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM