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

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

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

    聶永的博客

    記錄工作/學(xué)習(xí)的點(diǎn)點(diǎn)滴滴。

    100萬并發(fā)連接服務(wù)器筆記之Erlang完成1M并發(fā)連接目標(biāo)

    前言

    使用Erlang語言也寫一個(gè)測試和前面大同小異的測試,在100萬個(gè)并發(fā)連接用戶情況下,就是想觀察一下極顯情況下的表現(xiàn)。
    這個(gè)測試使用了優(yōu)秀的Erlang界的明星框架cowboy,加單易用的接口,避免了我們對HTTP棧再次進(jìn)行閉門造車。

    測試Erlang服務(wù)器

    運(yùn)行在VMWare Workstation 9中,64位Centos 6.4系統(tǒng),分配14.9G內(nèi)存左右,雙核4個(gè)線程,服務(wù)器安裝Erlang/OTP R16B,最新版本支持異步代碼熱加載,很贊。

    下載安裝

    本系統(tǒng)已經(jīng)提前安裝JDK,只需要安裝Erlang好了。

    安裝依賴

    
    
    yum install build-essential m4
    yum install openssl
    yum install openssl-devel
    yum install unixODBC
    yum install unixODBC-devel
    yum -y install openssl make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel
    yum install xsltproc fop

    源代碼安裝

    #wget https://elearning.erlang-solutions.com/binaries/sources/otp_src_R16B.tar.gz
    #tar xvf otp_src_R16B.tar.gz
    cd otp_src_R16B
    ./configure --prefix=/usr/local/erlang --enable-hipe --enable-threads --enable-smp-support --enable-kernel-poll
    make
    make install
    

    添加到環(huán)境變量中(/etc/profile)

    export ERL_HOME=/usr/local/erlang export PATH=$ERL_HOME/bin:$PATH
    

    保存生效

    source /etc/profile
    

    測試進(jìn)程創(chuàng)建

    這里拷貝《Erlang程序設(shè)計(jì)》一書提供的processes.erl源碼,稍作修改。

    創(chuàng)建一百萬個(gè)進(jìn)程,看看大概花費(fèi)多少時(shí)間。

    [yongboy@base erlang]$ erl +P 10240000
    Erlang R16B (erts-5.10.1) [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
    Eshell V5.10.1 (abort with ^G)
    1> processes:max(200000).
    Maxmium allowed process is 16777216 Process spawn time=1.1 (2.68) microseconds ok
    2> processes:max(200000).
    Maxmium allowed process is 16777216 Process spawn time=1.7 (2.33) microseconds ok
    3> processes:max(200000).
    Maxmium allowed process is 16777216 Process spawn time=1.55 (2.12) microseconds ok
    4> processes:max(1000000).
    Maxmium allowed process is 16777216 Process spawn time=2.97 (3.967) microseconds ok
    5> processes:max(1000000).
    Maxmium allowed process is 16777216 Process spawn time=2.4 (2.729) microseconds ok
    6> processes:max(1000000).
    Maxmium allowed process is 16777216 Process spawn time=2.19 (2.735) microseconds ok
    7> processes:max(10000000).
    Maxmium allowed process is 16777216 Process spawn time=3.328 (4.2777) microseconds ok
    8> processes:max(10000000).
    Maxmium allowed process is 16777216 Process spawn time=3.144 (3.1361) microseconds ok
    9> processes:max(10000000).
    Maxmium allowed process is 16777216 Process spawn time=3.394 (3.2051) microseconds ok
    

    恩,創(chuàng)建1000萬個(gè)進(jìn)程,每一個(gè)進(jìn)程花費(fèi)3.4微秒(μs)的CPU時(shí)間,相當(dāng)于4.3微秒(μs)的消耗時(shí)間(亦即消耗的真實(shí)時(shí)間),在一定量的區(qū)間內(nèi),其值變化,可以看做是一個(gè)常量。

    初始化小問題

    Cowboy初始化需要事項(xiàng)

    我們做的簡單程序,使用了非常受歡迎的cowboy框架,其啟動函數(shù):

    cowboy:start_http(my_http_listener, 100,
    [{port, 8000}],
    [{env, [{dispatch, Dispatch}]}]
    ),
    

    Cowboy默認(rèn)支持1024個(gè)連接,服務(wù)器端輸出:

    online user 1122 online user 1123 

    停滯于此,后續(xù)的連接只能排隊(duì)等候了。

    這里設(shè)置支持無限個(gè)連接好了。

    {max_connections, infinity}
    

    話說,Cowboy為Erlang世界的明星產(chǎn)品,絕對值得一試!

    Erlang默認(rèn)創(chuàng)建進(jìn)程限制

    Erlang在我的機(jī)器上默認(rèn)允許創(chuàng)建的線程也是有限的:

    erlang:system_info(process_limit).
    262144
    

    才26萬個(gè),不夠用。在啟動腳本(start.sh)處添加允許創(chuàng)建的最大線程支持:

    #!/bin/sh
    erl +K true +P 10240000 -sname testserver -pa ebin -pa deps/*/ebin -s htmlfilesimple\
    -eval "io:format(\"Server start with port 8000 Success!~n\")."

    腳本啟動后現(xiàn)在在erl shell中測試一下:

    erlang:system_info(process_limit).
    16777216
    

    數(shù)量完全夠用了。

    開啟erlang的epoll屬性

    +K true | false 是否開啟kernel poll,就是epoll;
    

    不開啟,測試過程中,在內(nèi)存完好情況下,經(jīng)常會有連接失敗情況。

    使用cowboy_req:compact降低內(nèi)存占用

    一旦你從request對象中獲取到足夠的信息,以后不再獲取其附加屬性時(shí),調(diào)用compact/1函數(shù)可去除無用屬性,起到節(jié)省內(nèi)存作用。
    程序里面調(diào)用如下:

    init(_Any, Req, State) -> NowCount = count_server:welcome(),
    io:format("online user ~p :))~n", [NowCount]),
    output_first(Req),
    Req2 = cowboy_req:compact(Req),
    {loop, Req2, State, hibernate}.
    

    在本例中精測壓縮內(nèi)存效果不明顯,因?yàn)?,測試端輸出的HTTP頭部壓根就沒有幾個(gè)。

    Cowboy無法處理沒有header的HTTP請求

    這里需要牢記,也不能算是BUG,前面的client2.c源碼,就未曾設(shè)置HTTP Header元數(shù)據(jù),需要做些簡單修改,修改之后的測試端程序文件名為client5.c, 可以到這里 下載client.c

    Cowboy處理長連接

    Cowboy很貼心的提供了cowboy_loop_handler behaviour。在init/3函數(shù)中,可以進(jìn)入休眠狀態(tài),節(jié)省內(nèi)存,消息到達(dá)時(shí),被喚醒,值得一贊! 其定義如下: 注意hibernatetimeout參數(shù),按照實(shí)際需求返回即可。

    htmlfile_handler示范代碼如下:

    100萬并發(fā)連接達(dá)成

    測試過程跌跌撞撞的,雖然這中間因?yàn)閮?nèi)存問題拋出若干的異常,但也達(dá)到100W連接的數(shù)量

    online user 1022324 :))
    online user 1022325 :))
    online user 1022326 :))
    online user 1022327 :))
    online user 1022328 :))
    online user 1022329 :))
    online user 1022330 :))
    online user 1022331 :))
    online user 1022332 :))
    online user 1022333 :))
    online user 1022334 :))
    online user 1022335 :))
    online user 1022336 :))
    online user 1022337 :))
    online user 1022338 :))
    

    可以看到狀態(tài)信息

    算一下: 14987952K = 14636M
    14987952/1022338 = 14.7K/Connection

    未啟動時(shí)的內(nèi)存情況:

     total used free shared buffers cached
    Mem: 14806 245 14561 0 12 60
    -/+ buffers/cache: 172 14634
    Swap: 3999 0 3999
    

    啟動后的內(nèi)存占用情況:

     total used free shared buffers cached
    Mem: 14806 435 14370 0 12 60
    -/+ buffers/cache: 363 14443
    Swap: 3999 0 3999
    

    用戶量達(dá)到1022338數(shù)量后的內(nèi)存一覽:

     total used free shared buffers cached
    Mem: 14806 14641 165 0 1 5
    -/+ buffers/cache: 14634 172
    Swap: 3999 1068 2931
    

    可以看到,當(dāng)前內(nèi)存不夠用了,需要虛擬內(nèi)存配合了。

    查看一下當(dāng)前進(jìn)程的內(nèi)存占用

    ps -o rss= -p `pgrep -f 'sname testserver'`
    4869520
    

    這樣算起來,系統(tǒng)為每一個(gè)進(jìn)程持有 4869520/1022338 = 4.8K 內(nèi)存。 這個(gè)值只是計(jì)算物理內(nèi)存,實(shí)際上連虛擬內(nèi)存都占用了,估計(jì)在4.8K-6.8K之間吧。

    和C語言相比,內(nèi)存占用相當(dāng)大,我虛擬機(jī)器分配的15G內(nèi)存,也僅僅處理達(dá)到100萬的連接,已經(jīng)接近極限時(shí),會發(fā)現(xiàn)陸陸續(xù)續(xù)的有連接失敗。

    不得不說的代碼熱加載

    運(yùn)行時(shí)系統(tǒng)的代碼熱加載功能,在這個(gè)實(shí)例中,通過vi修改了htmlfile_handler.erl文件,主要修改內(nèi)容如下:

    io:format("online user ~p :))~n", [NowCount]),
    ......
    io:format("offline user ~p :(( ~n", [NowCount]).
    

    執(zhí)行make,編譯

    [root@base htmlfilesimple]# make
    ==> ranch (get-deps)
    ==> cowboy (get-deps)
    ==> htmlfilesimple (get-deps)
    ==> ranch (compile)
    ==> cowboy (compile)
    ==> htmlfilesimple (compile)
    src/htmlfile_handler.erl:5: Warning: record status is unused
    src/htmlfile_handler.erl:29: Warning: variable 'Reason' is unused
    Compiled src/htmlfile_handler.erl
    

    很好,非常智能的rebar,自動只編譯了htmlfile_handler.erl一個(gè)文件,然后通知Erlang的運(yùn)行環(huán)境進(jìn)行代碼熱替換吧。

    (testserver@base)4> code:load_file(htmlfile_handler). 

    查看日志輸出控制臺,可以看到已經(jīng)生效,同時(shí)也保存著到狀態(tài)數(shù)據(jù)等。

    非常利于運(yùn)行時(shí)調(diào)試,即不傷害在線狀態(tài)數(shù)據(jù),又能即時(shí)修改,贊!但生產(chǎn)環(huán)境下,一般都是版本切換,OTP的版本切換,測試或馬上修改bug時(shí),著實(shí)有些復(fù)雜。

    小結(jié)

    和C相比,處理相同的事情(100萬并發(fā)連接),及其簡單,但Erlang會需要更多的內(nèi)存,廉價(jià)的內(nèi)存可以滿足,只是我的搭建在Vmware中的虛擬機(jī)器已經(jīng)達(dá)到了它所要求的極限。
    完整的源代碼,可點(diǎn)擊這里下載

    posted on 2013-04-28 17:17 nieyong 閱讀(16890) 評論(1)  編輯  收藏 所屬分類: C1M

    評論

    # re: 100萬并發(fā)連接服務(wù)器筆記之Erlang完成1M并發(fā)連接目標(biāo) 2014-02-20 10:17 西嶺風(fēng)清

    真巧,去年我用C++開發(fā)了一個(gè)推送服務(wù)器,4月份測完上線使用。

    測試的時(shí)候測到了110w并發(fā)(2.6.2以下最多能到1024k,在這個(gè)之上的kernel單機(jī)有辦法改到超過1024k句柄),沒有出現(xiàn)博主出現(xiàn)的掉線情況,內(nèi)存消耗貌似要小一點(diǎn),一個(gè)連接平均均攤8-10k左右。

    不過C++開發(fā)起來真累,維護(hù)起來也很麻煩,我看到此文后,深深陷入到造HTTP輪子的自責(zé)當(dāng)中。

    我今年一開始想把它變成JNI+Java方式,碰巧看到博主的做法,到時(shí)候試試,謝謝博主。  回復(fù)  更多評論   

    公告

    所有文章皆為原創(chuàng),若轉(zhuǎn)載請標(biāo)明出處,謝謝~

    新浪微博,歡迎關(guān)注:

    導(dǎo)航

    <2013年4月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011

    統(tǒng)計(jì)

    常用鏈接

    留言簿(58)

    隨筆分類(130)

    隨筆檔案(151)

    個(gè)人收藏

    最新隨筆

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 亚洲欧洲日产国码在线观看| 亚洲好看的理论片电影| 特级毛片爽www免费版| 亚洲成亚洲乱码一二三四区软件| 18pao国产成视频永久免费| 亚洲 欧洲 日韩 综合在线| 亚洲国产香蕉人人爽成AV片久久 | 日本免费人成网ww555在线| 亚洲国产av一区二区三区丶| 吃奶摸下高潮60分钟免费视频| 免费h视频在线观看| 久久亚洲国产成人影院| 亚洲午夜久久久久久噜噜噜| 一个人看www在线高清免费看| 国产成人精品免费大全| 亚洲18在线天美| 亚洲国产精品一区二区成人片国内| 成年轻人网站色免费看| 免费萌白酱国产一区二区三区| 亚洲AV无码精品国产成人| 亚洲精品线在线观看| 亚洲?V乱码久久精品蜜桃| 国产精品色拉拉免费看| 中文在线观看国语高清免费| 久久精品国产亚洲av品善| 亚洲视频欧洲视频| 伊人久久亚洲综合| 全黄a免费一级毛片人人爱| 国产免费不卡视频| 久久这里只精品热免费99| 一级特黄aaa大片免费看| 亚洲熟妇无码一区二区三区| 亚洲一区精品中文字幕| 国产亚洲精品无码拍拍拍色欲| 国产福利免费在线观看| 91香蕉成人免费网站| 男人都懂www深夜免费网站| selaoban在线视频免费精品| 久久亚洲精品无码网站| 亚洲成人激情小说| 亚洲国产精品一区二区久|