通用高性能網絡框架的研究與應用
為簡化應用軟件的網絡通信開發工作,提出了一種基于異步網絡通信機制的通用高性能網絡框架方案,滿足應用軟件的網絡通信和業務處理要求,提高軟件開發成果的復用性。方案基于Boost.Asio庫實現Proactor模式的跨平臺高性能異步網絡通信,使用可擴展標記語言(Extensible Markup Language,XML)實現框架內外的功能業務關聯配置滿足通用要求,通過將網絡連接及關聯數據抽象為網絡會話實現消息數據高效傳遞,支持自定義擴展滿足個性化業務需求,是一種經濟的滿足功能和性能需求的輕量級網絡框架。
內容目錄:
0 引 言
1 相關技術介紹
2 通用高性能網絡框架
2.1 框架架構
2.2 框架內部關聯關系
2.3 業務協議接口設計
3 系統實現的關鍵技術
3.1 網絡會話設計
3.2 組件化設計
4 框架應用
5 結 語
0、引 言
隨著網絡技術的飛速發展和廣泛應用,不管是面向企業用戶還是個人消費者,網絡功能都是應用軟件不可或缺的基本功能。目前應用軟件的網絡功能開發具有過程復雜、周期漫長、通信協議不統一和復用程度低等缺點,改善并簡化網絡通信開發過程是當前應用軟件研發的重要研究方向。互聯網上的開源網絡庫也比較多,比如Mudoo、Boost.Asio、ACE、LibEvent等,這些開源庫都實現了網絡通信功能封裝,但是無法與應用業務實現按需關聯,另外必須二次開發才能進一步滿足應用軟件的具體業務需求。因此,研究一種通用的高性能網絡框架對于簡化應用軟件的網絡開發工作,提高軟件開發成果的復用性具有重要作用。本文基于異步網絡通信機制,提出了一種通用的高性能網絡框架實現方案,能夠滿足應用軟件的網絡通信和業務處理需求,使研發人員更加專注于業務層面的用戶需求。
1、相關技術介紹
Boost是一個開源的跨平臺C++程序庫,它功能組件眾多,很多組件已被收錄進C++標準,所以也被稱為C++“準”標準庫。Boost庫提供了常用的網絡通信、并發編程、日期與時間、字符串、正則表達式等模塊,彌補了C++語言在許多方面的不足,極大增強了C++語言的活力和生命力。Asio是Boost庫中非常出名的用于處理網絡通信的輕量級類庫,支持高并發輸入/輸出(Input/Output,I/O)處理和多種網絡協議,內部集成了網絡編程常用的操作接口,并支持同步和異步調用方式,相關接口以類的形式進行封裝并對外提供調用。由于綜合表現出色,Boost.Asio庫正逐漸成為C++網絡庫的工業化標準,被越來越多的網絡應用作為基礎框架。
Boost.Asio庫的異步網絡通信采用Proactor模式。在Proactor模式中,任意網絡操作(accept、connect、send、receive等)都是調用的異步I/O,在調用相關操作接口時只是向操作系統進行了操作注冊,由操作系統進行實際的操作處理,待操作系統完成操作后再通過回調主動通知,實現后續的業務流程。
2、通用高性能網絡框架
本文設計的網絡框架采用層次化、模塊化思路,使用C++編程語言進行開發,基于Boost.Asio庫實現高性能異步網絡通信,通過XML實現框架內外的關聯配置,適用于傳輸控制協議(Transmission Control Protocol,TCP)、用戶數據報協議(User Datagram Protocol,UDP)、Internet控制報文協議(Internet Control Message Protocol,ICMP)、原始套接字(Raw Socket,RAW)網絡通信模式,可以滿足軟件輕量級、高并發的網絡通信需求,具有跨平臺、高性能、通用性、伸縮性、可維性和擴展性等特點。
2.1 框架架構

圖1 通用高性能網絡框架架構
框架依據層次化設計思路,從下到上依次分為共享操作層、服務調度層、業務邏輯層和業務接口層四個層級。共享操作層包含與業務邏輯無關的可復用基礎操作集合,這些常用操作在優秀開源庫的基礎上進行二次封裝,實現已有成果的重用,避免重復開發;服務調度層是整個框架的核心,以Boost.Asio庫的異步網絡通信為基礎,進行框架內外消息數據的通信調度,實現業務邏輯與協議數據的“透明”耦合;業務邏輯層包含具體業務操作集合,依據模塊化思路進行業務邏輯獨立封裝,業務之間通過統一接口進行關聯操作;業務接口層實現框架內外通信接口,內部接口以接口函數方式基于統一格式進行封裝,外部接口以網絡服務方式對外提供。
服務調度層由異步I/O、消息調度子層、網絡協議子層和業務協議子層組成,通過接口進行通信。異步I/O基于Boost.Asio庫實現大規模網絡連接高效率并發處理;消息調度子層將網絡連接抽象為網絡會話進行全生命期的異步跟蹤,對異步I/O的網絡操作通知及時分配工作線程池中的空閑線程進行處理,將任意業務邏輯與網絡操作行為(accept、connect、send、receive、close)的關系通過狀態機模型建立異步關聯,實現任意復雜業務的操作流水化,并通過XML配置實現消息調度、網絡協議、業務協議和業務邏輯之間的按需關聯;網絡協議子層實現TCP、UDP等通用網絡協議的異步調用接口;業務協議子層實現業務數據格式解析和封裝,使業務邏輯不因業務協議的變化而修改,達到業務協議對業務邏輯透明。
2.2 框架內部關聯關系

圖2 框架內部關聯關系
服務調度層的異步I/O負責具體的網絡操作,網絡協議子層負責網絡數據(包含業務數據和管理數據)收發,并在對應的網絡操作完成后回調通知消息調度子層,由消息調度子層依據網絡操作行為進行協議數據解析驗證,依據解析驗證結果調用業務邏輯層的具體業務模塊進行業務邏輯處理。
業務過程如果需要進行業務數據收發,則通過業務協議子層進行數據收發通知,并通過網絡協議子層完成網絡操作。在發送數據時,通過業務協議子層完成業務協議數據封裝,實現業務邏輯與協議數據格式的“透明”耦合,業務邏輯不用關心具體的業務協議數據格式,進入業務邏輯都是已經剝離相關業務協議格式的原始業務數據,實現相同業務邏輯在不同項目的重復使用。
2.3 業務協議接口設計
業務協議子層采用C++多態機制,完成業務協議數據網絡收發通知、格式封裝和解析驗證,實現業務協議格式與業務邏輯的彼此獨立和按需組合。
框架支持定長和不定長兩種業務協議數據。定長業務協議數據區分協議頭和協議體兩部分,網絡接收數據時先收協議頭,然后進行協議頭解析并獲取協議體長度,接著繼續接收協議體。待對應的協議頭和協議體數據接收完成后,再進行業務數據的完整解析驗證,并在完成驗證后將數據送入業務模塊處理。對于沒有區分固定協議頭和協議體的不定長數據,按照“應收盡收”原則,盡可能接收足夠數據。網絡發送數據前對待發送數據按照業務協議格式進行封裝,然后再進行發送。
業務協議子層模塊部分接口設計如下:
// 接收固定協議頭
virtual int async_recv_head(IN CSession *session,IN u_int timeout) = 0;
// 接收固定協議體
virtual int async_recv_body(IN CSession *session,IN u_int timeout) = 0;
// 接收不固定協議數據
virtual int async_recv_some(IN CSession *session,IN u_int minlen,IN u_int timeout) = 0;
// 發送協議數據(協議頭+協議體)
virtual int async_send_buf(IN CSession *session,IN u_int timeout) = 0;
// 解析驗證接收到的協議頭
virtual int unpackaging_head(IN CSession *session) = 0;
// 解析驗證接收到的協議體
virtual int unpackaging_body(IN CSession *session) = 0;
// 封裝協議頭
virtual int packaging_head(IN CSession *session) = 0;
// 封裝協議體
virtual int packaging_body(IN CSession *session,IN const void *value = NULL,IN u_int value_size = 0,IN u_int value_len = 0) = 0;
3、系統實現的關鍵技術
3.1 網絡會話設計
為了確保數據在業務生命周期內的完整性、有效性和唯一性,以及業務處理過程中對數據訪問的便捷性和及時性,框架將網絡連接及關聯數據抽象為網絡會話(自定義類CSession),實現網絡連接生命期內統一管理。網絡會話涉及業務過程中發生的完整關聯數據集合,包含網絡套接字、數據庫連接、業務模塊、業務數據等,如圖3所示。

圖3 網絡會話組成
網絡會話的生命周期與網絡連接保持一致,隨著網絡連接的建立而創建,網絡連接的關閉而銷毀。但是在大規模網絡連接并發訪問場景中,為避免頻繁進行資源分配、銷毀而影響業務性能,在關閉網絡連接時并不進行網絡會話的銷毀,而只是進行網絡套接字的關閉和關聯數據的復位,并在新的網絡連接建立后再次關聯使用;數據庫連接通過配置實現數據庫類型及其它數據庫訪問參數的讀取,基于“一線程一實例”原則進行創建,運行多少個工作線程就建立相應數量的數據庫連接,并在工作線程進行業務處理前與網絡會話進行綁定,實現業務過程中基于網絡會話的數據庫訪問操作,又避免多線程并發業務導致的數據庫訪問沖突;業務協議子層在完成業務協議數據解析后,能夠獲取業務標識,并依據業務標識在首次業務處理前進行業務模塊的創建,并在網絡會話關閉時進行業務模塊的銷毀;業務數據包含獨立的網絡發送和接收緩沖區,以便實現網絡全雙工通信,在業務過程中可以依據需要進行收發緩沖區的交換而避免數據拷貝,實現業務數據快速發送。
在業務過程中,業務A創建了業務B,此時稱業務A為父業務,業務B為子業務。父業務創建子業務時,通過將父業務的網絡會話傳遞給子業務,此時父業務和子業務都可以獲得對方的網絡會話,實現相同網絡會話在多個關聯業務間流轉,滿足業務關聯數據的快速共享訪問,提高業務消息傳遞效率。
3.2 組件化設計
框架的所有模塊依據“一業務、一模塊”原則,使用C++類進行業務邏輯封裝,并生成獨立動態庫。業務間通過接口進行耦合,特定業務流程或者邏輯修改不影響其它業務,同時采用XML配置決定上線運行的模塊以及模塊間的業務關聯關系。框架通過網絡服務對外提供接口,并使用XML配置網絡服務的相關參數,實現網絡服務與業務的關聯綁定。如圖4所示。

圖4 框架配置
網絡服務的配置涉及網絡參數、網絡協議模塊、業務協議模塊、消息調度模塊、數據庫模塊和業務模塊集合等。網絡參數包含服務地址和端口、連接超時值、收發數據超時值、收發數據緩沖區大小等;網絡協議模塊確定網絡服務所采用的通用基礎網絡協議,如TCP、UDP、ICMP、原始套接字等;業務協議模塊與具體項目相關,實現具體業務邏輯關聯的應用層數據格式;消息調度模塊決定采用哪一種消息調度器,實現消息數據的調度處理;數據庫模塊包含項目采用的數據庫類型(如MySQL)、數據庫訪問參數(如登錄賬戶信息等)和訪問數據庫的接口(如unixODBC接口);業務模塊通過業務標識唯一確認具體業務,只有配置在該網絡服務中的業務模塊才允許被觸發調用。
框架部分XML配置如下:
<md note="消息調度器列表" > <item id="md.general" file="libmd.general.so" note="通用消息調度模塊" /> …… </md> <ntp note="網絡協議模塊" > <item id="ntp.tcp" file="libntp.tcp.so" note="TCP網絡協議模塊" /> …… </ntp> <btp note="業務協議模塊" > <item id="btp.http" file="libbtp.http.so" note="http業務協議" /> …… </btp> <module note="業務模塊" > <item id="s0001" file="libmodule.s0001.so" note="身份認證服務端模塊" /> …… </module> <dbi note="數據庫接口模塊" > <item id="dbi.uodbc" file="libdbi.uodbc.so" note="UnixODBC接口" /> …… </dbi> <database note="數據庫配置" > <item id="db.test" type="mysql" dbi_id="dbi.uodbc" ipaddr="localhost" port="3306" name="test" …… note="測試數據庫" /> </database> <netsrv note="網絡服務配置" > <item id="netsrv.http" enable="true" md_id="md.general" ntp_id="ntp.tcp" btp_id="btp.http" db_id="db.test" ipaddr="127.0.0.1" port="80" …… note="HTTP服務"> <module bsid="auth.s" enable="true" mid="s0001" note="" /> …… </item> </netsrv>
4、框架應用
該框架在2G的可用內存中實現了20萬網絡連接并發收發數據測試,對接了達夢、金倉、MySQL等國產化和非國產化的多種類型數據庫,并已經在實際多個項目進行應用,涉及軟硬件結合項目和純軟件項目,涵蓋x86、PowerPC、龍芯、兆芯、飛騰、Windows、Linux、中科方德、中標麒麟等眾多軟硬件組合的非國產化和國產化環境。各個項目重用了除部分業務協議模塊、業務模塊外的框架其它成果,并依據實際項目情況調整了部分框架參數,同時在此基礎上進行擴展開發,實現了工作成果的復用。
5、結 語
本文針對當前應用軟件研發過程中出現的網絡功能開發復雜、開發成本大、網絡框架無法通用等問題研究了一種通用的高性能網絡框架,并基于C++編程語言進行了實現,使用第三方軟件對實現結果進行了通信效果測試,驗證了框架的應用效果。同時,該框架已經在多個項目進行復用,滿足了不同項目的業務需求,降低了項目的研發成本。