<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    聶永的博客

    記錄工作/學習的點點滴滴。

    基于Erlang OTP構建一個TCP服務器

    套接字模式

    主動模式(選項{active, true})一般讓人很喜歡,非阻塞消息接收,但在系統無法應對超大流量請求時,客戶端發送的數據快過服務器可以處理的速度,那么系統就可能會造成消息緩沖區被塞滿,可能出現持續繁忙的流量的極端情況下,系統因請求而溢出,虛擬機造成內存不足的風險而崩潰。

    使用被動模式(選項{active, false})的套接字,底層的TCP緩沖區可用于抑制請求,并拒絕客戶端的消息,在接收數據的地方都會調用gen_tcp:recv,造成阻塞(單進程模式下就只能消極等待某一個具體的客戶端套接字,很危險)。需要注意的是,操作系統可能還會做一些緩存允許客戶端機器繼續發送少量數據,然后才會將其阻塞,此時Erlang尚未調用recv函數。

    混合型模式(半阻塞),使用選項{active, once}打開,主動僅針對一個消息,在控制進程發送完一個數據消息后,必須顯示調用inet:setopts(Socket, [{active, once}])重新激活以便接受下一個消息(在此之前,系統處于阻塞狀態)。可見,混合型模式綜合了主動模式和被動模式的兩者優勢,可實現流量控制,防止服務器被過多消息淹沒。

    以下TCP Server代碼,都是建立在混合型模式(半阻塞)基礎上。

    prim_inet相關說明

    prim_inet沒有官方文檔,可以認為是對底層socket的直接包裝。淘寶yufeng說,這是otp內部實現的細節 是針對Erlang庫開發者的private module,底層模塊,不推薦使用。但在Building a Non-blocking TCP server using OTP principles示范中演示了prim_inet操作Socket異步特性。

    設計模式

    一般來說,需要一個單獨進程進行客戶端套接字監聽,每一個子進程進行處理來自具體客戶端的socket請求。

    Building a Non-blocking TCP server using OTP principles示范中,子進程使用gen_fsm處理,很巧妙的結合狀態機和消息事件,值得學習。

    Erlang: A Generalized TCP Server文章中,作者也是使用此模式,但子進程不符合OTP規范,因此個人認為不是一個很好的實踐模式。

    simple_one_for_one

    簡易的一對一監督進程,用來創建一組動態子進程。對于需要并發處理多個請求的服務器較為合適。比如socket 服務端接受新的客戶端連接請求以后,需要動態創建一個新的socket連接處理子進程。若遵守OTP原則,那就是子監督進程。

    TCP Server實現 

    基于標準API簡單實現

    也是基于{active, once}模式,但阻塞的等待下一個客戶端連接的任務被拋給了子監督進程。

    看一下入口tcp_server_app吧

    讀取端口,然后啟動主監督進程(此時還不會監聽處理客戶端socket請求),緊接著啟動子監督進程,開始處理來自客戶端的socket的連接。

    監督進程tcp_server_sup也很簡單:

    需要注意的是,只有調用start_child函數時,才真正調用tcp_server_handler:start_link([LSock])函數。

    tcp_server_handler的代碼也不復雜:

    代碼很精巧,有些小技巧在里面。子監督進程調用start_link函數,init會返回{ok, #state{lsock = Socket}, 0}. 數字0代表了timeout數值,意味著gen_server馬上調用handle_info(timeout, #state{lsock = LSock} = State)函數,執行客戶端socket監聽,阻塞于此,但不會影響在此模式下其它函數的調用。直到有客戶端進來,然后啟動一個新的子監督進程tcp_server_handler,當前子監督進程解除阻塞。

     

    基于prim_inet實現

    這個實現師從于Non-blocking TCP server using OTP principles一文,但子進程改為了gen_server實現。

    看一看入口,很簡單的:

    監督進程代碼:

    策略不一樣,one_for_one包括了一個監聽進程tcp_listener,還包含了一個tcp_client_sup進程樹(simple_one_for_one策略)

    tcp_listener單獨一個進程用于監聽來自客戶端socket的連接:

    很顯然,接收客戶端的連接之后,轉交給tcp_client_handler模塊進行處理:

    和標準API對比一下,可以感受到異步IO的好處。

    小結

    通過不同的模式,簡單實現一個基于Erlang OTP的TCP服務器,也是學習總結,不至于忘記。

    您若有更好的建議,歡迎告知,謝謝。

    參考資料

    1. Building a Non-blocking TCP server using OTP principles
    2. Erlang: A Generalized TCP Server
    3. 《Erlang程序設計》
    4. 《Erlang/OTP并發編程實戰》

    posted on 2012-10-24 18:14 nieyong 閱讀(13081) 評論(1)  編輯  收藏 所屬分類: Socket

    評論

    # re: 基于Erlang OTP構建一個TCP服務器 2013-12-26 15:51 yf2800z

    你好,我用了你的第一個服務端做了下實驗,我的系統是mac 10.9osx 在啟動客戶端連接后 我連接了243個連接 就不能在連接了 這是為什么 能具體的指導下嗎?  回復  更多評論   

    公告

    所有文章皆為原創,若轉載請標明出處,謝謝~

    新浪微博,歡迎關注:

    導航

    <2012年10月>
    30123456
    78910111213
    14151617181920
    21222324252627
    28293031123
    45678910

    統計

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 成人久久免费网站| 成全高清在线观看免费| 亚洲伊人tv综合网色| 8x8x华人永久免费视频| 色哟哟国产精品免费观看| 日韩亚洲一区二区三区| 亚洲第一成人影院| 大学生a级毛片免费观看| 一级一黄在线观看视频免费| 亚洲综合精品第一页| 亚洲午夜电影一区二区三区| 亚洲av无码乱码在线观看野外 | 免费va在线观看| 日本高清不卡aⅴ免费网站| 美女羞羞视频免费网站| 久久亚洲精品成人无码网站| 亚洲熟妇av一区二区三区| 男女超爽刺激视频免费播放 | 四虎AV永久在线精品免费观看| 无码国产精品一区二区免费虚拟VR | 国产精品亚洲片夜色在线| 亚洲视频在线观看不卡| 亚洲成A人片777777| 亚洲无人区午夜福利码高清完整版 | 成年人性生活免费视频| 国产精品综合专区中文字幕免费播放 | 成人免费夜片在线观看| 国产91成人精品亚洲精品| 亚洲AV成人无码网天堂| 伊人久久综在合线亚洲2019| 国产AV无码专区亚洲Av| 久久综合日韩亚洲精品色| 亚洲国产成人a精品不卡在线 | 一级看片免费视频| av电影在线免费看| 九九99热免费最新版| a毛片视频免费观看影院| 免费人成又黄又爽的视频在线电影 | A级毛片成人网站免费看| 国产午夜无码精品免费看动漫| 九九精品成人免费国产片|