程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> MarioTCP: Multi Libvent TCP Server 一個高性能的TCP服務器

MarioTCP: Multi Libvent TCP Server 一個高性能的TCP服務器

編輯:關於C語言

我在sourceforge上建了這個開源項目,把項目介紹首發在csdn:http://blog.csdn.net/everlastinging/article/details/10894493 沒想到大家評價還不錯,所以再發一下,希望更多的人看看他,做大型游戲服務器、P2P服務器的底層可以用他,還沒畢業的計算機碩士也可以學這個迅速積累IT技術經驗。


MrioTCP,超級馬裡奧,顧名思義,他不僅高效,而且超級簡易和好玩。同時他可以是一個很簡潔的Linux C 開發學習工程。毫不誇張的說,如果全部掌握這一個工程,你會成為一個Linux C的牛人;當然,你也可以通過源碼包的mario.c(maritcp服務器示例程序)來學習,可以很快入門上手進行Linux C開發。

經過兩個多月的測試編寫c++客戶端測試及調優系統參數),測試結果得到單機最大帶寬吞吐1000M,測試最高TCP長連接100萬,每秒處理連接數達4萬,此時系統壓力load值很低。總之,它可以發揮一台服務器的最大極限以提供最高性能的服務;而且經過完備測試,運行穩定且占用系統資源非常少。

他是建立在Sourceforge上的一個開源項目,由源碼的作者馮建華(JohnFong)發起。源碼可以在Sourceforge上下載。

sourceforge下載:https://sourceforge.net/projects/mariotcp/files/latest/download

csdn下載:http://download.csdn.net/detail/everlastinging/6195605

51cto下載:http://down.51cto.com/data/935913

Getting Started


用MarioTCP來建立一個性能強大的TCP服務器非常簡易!

  工程源碼包就是一個非常簡潔的例子,生成了一個tcp服務器程序:maritcp。
  源碼包中:
  mario.c是簡易例子的main程序,直接make可以編譯出maritcp,一個tcp服務器,業務邏輯只有一個功能:統計同時在線socket數、每隔1分鐘輸出一次。
  mario文件夾,MarioTCP的核心代碼,make可以直接編譯出靜態的libmario.a。MarioTCP核心架構後續會介紹。
  test文件夾,是一個稍顯簡陋的客戶端測試程序,通過與服務器建立連接、發送LOGIN包登陸服務器,此時maritcp服務器會使同時在線加1,客戶端斷開時服務器在線數減1。

現在講一下如何定制一個自己業務邏輯的tcp服務器,只需五步:
  1、初始化SERVER
  SERVER *server = init_server(conf->port, conf->workernum, conf->connnum, conf->timeout, conf->timeout);
  傳入參數分別是:
  服務器Listen端口,工作線程數,每個線程支持的連接數,讀超時時間,寫超時時間。
  workernum * connum 就是服務器支持的長連接數,一個worker可以輕松支持10萬長連接。

2、實現業務邏輯函數並注冊
  具體業務邏輯函數請見Function模塊。可通過mario.h中定義的名為“regist_*”的函數來注冊。

/*
  *  注冊業務處理函數
  /
  void regist_akg_func(uint16 id, FUNC_PTR func);
  id可以是0-65535的任意數,此id封裝在MarioTCP的協議中見本文最後)。
  id的范圍,可以根據業務邏輯來定制,例如maritcp通過protocol.h中定義的CMD結構體來設定:
  typedef enum _CMD {
  CMD_FUNCTION_BASE = 0x6100,
  CMD_FUNCTION_LOGIN = 0x6101
  } CMD;

如果你想為maritcp增加一個"say_hello"的服務,可以這麼做:
  1)在CMD中增加:CMD_FUNCTION_SAY_HELLO = 0x602
  2) 在function中增加函數:
  sint32 say_hello(CONN c) {
  I)通過CONN來解析客戶端發過來請求的參數
  II)將“hello”設定到c->out_buf
  III)bufferevent_write(c->bufev, c->out_buf, hrsp->pkglen);
  IV)return 0;
  }
  3)在mario.c中增加:regist_akg_func(CMD_FUNCTION_SAY_HELLO, say_hello);

怎麼樣?自己定制業務邏輯,還是很簡單高效吧!

3、啟動日志線程start_log_thread()
  MarioTCP的日志功能封裝還不夠好,在“go on 1.0.0”頁面中繼續討論...

4、啟動服務器start_server((void*) server);
  OK,一個可以支持100萬甚至更多長連接的TCP服務器,誕生了!


Go On 1.0.0


第一個發布版本為0.9.9,盡管用這個包,通過幾分鐘就可以實現一個定制了你的業務邏輯的、穩定高效的TCP服務器,但是MarioTCP還有很多有待完善的地方,讓我們一起盡快解決如下問題,讓MarioTCP-1.0.0盡快發布!


1、MarioTCP協議如何優化
  為了使MarioTCP足夠安全,規定了一個簡易的MarioTCP協議,經過三次握手連接到MarioTCP的client,接下來發的包要求格式必須是“HEAD+Data”的形式,而HEAD結構體定義在mario_akg.h中:
  typedef struct _HEAD {
  uint32 stx;
  uint16 pkglen;
  uint16 akg_id;
  } HEAD;
  pkglen是整個包的長度,即“HEAD+Data”。
  akg_id及自定義的業務邏輯函數對應的id,例如“Getting Started”頁面中的CMD_FUNCTION_SAY_HELLO
  stx是你自定義的協議密文,通過regist_stx(uint32 stx)來注冊(見mario.c)

盡管MarioTCP的協議足夠簡單了,而且協議最開頭的密文可以自定義,但是是否可以更簡單或者無協議,以最大程度的方便開發使用,需要大家的建議和幫助!

2、日志系統過於死板
  MarioTCP有一套自成系統的日志功能,但是比較晦澀難懂。
  接下來再展開...

3、業務邏輯穩定性支持
  MarioTCP對於網絡連接和讀寫,非常高效和穩定。
  但是MarioTCP的線程池是固定個數的,且是全局唯一初始化的,死掉的線程不可再重啟;分配網絡任務的Master線程不具備監聽worker的功能,一個線程死掉了、任務卻還會一直分配過來,造成服務堆積且不處理。如果業務邏輯如果非常復雜和低效,就會出現這個問題。
  在大型線上項目中,用到MarioTCP的地方,都會通過業務邏輯模塊的監聽、告警及程序自動處理來避免上述問題。由於時間問題還沒有把此功能抽象到MarioTCP中。

  這件事情,近期我會抓緊處理。也希望有朋友建議和幫助!!


Why Supper


一、為什麼超級高效
  1、網絡服務用到的所有結構體和內存都是啟動程序時初始化的,無銷毀,無回收。
  無銷毀好理解,不解釋。
  無回收,是指所有內存單元拿來即用,用完及可,不用做reset操作。
  2、一個master線程進行accept
  經過測試發現多進程或線程進行accept和一個進程或線程accept,在極限壓力下區別不大。
  一個master比多個master好在不用再通過鎖來解決同步問題。
  3、master與worker時單一生產者消費者模式,完全無鎖通信
  不光accept無鎖,分配connection、後續的conncetion處理都是無鎖的。
  甚至業務邏輯見示例maritcp的統計在線數功能)、MarioTCP的日志系統這也是日志系統抽象不夠的一個原因,之前的設計太依賴於整體架構了)都是無鎖處理的!
  4、一個worker一套libevent環境
  libevent處理10萬長連接的網絡讀寫事件,其性能達到最大化了。
  每個worker都獨立一套libevent,這個結構經過測試,發現開銷很小、性能很高。

二、單機百萬長連接、四萬cps連接每秒)如何做測試得來
  1、設置系統最大文件數為unlimited
  2、設置系統的tcp內存內核參數到256M以上
  3、設置系統的ip到15個,那麼可服務的長連接數理論上最少15*(65535-1024)個
  4、用epoll或libevent開一個可同時連接5w的客戶端程序;程序還要實現每秒隨機挑選1000個連接斷掉,並再新創建1000個連接。另外在隨機挑選幾千連接發包。
  同時再多台機器上開啟20個客戶端,那麼就是100w長連接,每秒2w個連接斷掉、2w個新連接加入進來,並且有若干包發過來。
  5、設置服務端可重用SYN_WAIT的連接;客戶端斷連接的方式是主動斷掉防止客戶端程序端口堆積)
  總之很折騰的一個測試,前前後後大約2個多月才測試完畢。
  以上內容憑記憶寫的,怕有錯誤或疏漏,回頭為了公布測試代碼和測試結果給大家,會再次開發、測試並調整補過上述內容。


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved