• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            置頂隨筆

             

             

            最近給自己換了個老板,忙了一段時間,所以有幾個月沒寫博客,今后還是要爭取多寫啊,呵呵。

             

            換來新地方,第一件大的事情就是修改后端架構和通信協議,架構也設計得很普通,因為這邊的業務不需要太過復雜的后端,所以就簡單設計了一下,基本是參照web的模型,符合我一貫的向web學習的思想,弄了個gate管理入口,相當于web下的webserver,后端其他服務器掛在該gate下,相當于web模型下的appserver,或者fastcgi模型的fastcgi進程,gate上管理連接、合法性檢測、登錄、加密、壓縮、緩存。Gate和后端通信本來想參照fastcgi協議,但看了之后覺得fastcgi協議還是復雜了,所以就設計了一個更簡單的協議,gate和后端server之間可傳遞key:value型數據對,value不局限于字符串,可以是任意數據,這樣基本滿足了當前的需求,第一版放上去之后也運行良好,到今天也基本持續穩定運行快一個月了,沒出過什么事情。由于在gate這邊緩沖了job管理,所以后端server升級很方便,隨時可關閉更新,gate會在窗口時間內將未執行完成的任務重新提交,有此功能可放心大膽的升級后端,這個月這樣的工作做了幾次,在架構修改之前這樣的事情幾乎是不敢做的,因為一旦升級所有用戶全部斷開連接,而現在用戶則基本無感覺。Gate上的緩存層為后端減少了一些壓力,這個緩存是按照請求的md5key做的,并根據協議配置時效,有此cache后端大多數服務可不設計緩存或降低緩存設計的復雜度。Gate上針對敏感數據統一做了加密處理,主要是辛辛苦苦整理的數據不能輕易讓競爭對手竊去了,呵呵。Gate也做了壓縮,現在是針對>=128長度的包進行壓縮,使用了qlz,壓縮效率還是很不錯的,速度很快。目前gate后端掛接的既有win上的server也有linux上的server,這是一開始就這么規劃的,現在看來當初的目的達到了,混合發揮各自的優勢,有的項目在原有系統上跑得好好的,沒必要重新開發嘛。

             

            協議設計上本來我是計劃二進制混合json格式,以二進制為主,但嘗試了一個協議之后發現,這邊的小伙子們對直接操縱內存普遍技術不過關,他們大多是從java開始的,后來才學習c,對字符串用得很熟練,權衡之下采用了json為主,混合二進制為輔的方案,這樣修改之后的協議和他們之前使用的xml類似,就是更小更緊湊一點,使用方法上很類似,從現在的效果看還行,使用json格式為主的協議當然不能跟使用pb之類的相比,解析效率上大約單線程每秒解析20來萬10obj的對象,速度上不算太快但也不算太慢,對付一秒至多幾萬數據包的應用來說還是夠的,因為現在cpu計算能力普遍過剩,使用json的另個好處就是增刪字段很方便,各個版本之間不需要太考慮版本的問題,要是全用二進制格式就要麻煩很多了,在使用壓縮之后,目前的json格式協議比之前的xml協議減少了2/3的帶寬使用,總體效果還是可以的。使用json調試也很方便,我提供了一個工具,寫后端的就直接用該工具按照json格式收發數據,無需等client開發好了再去做后端,之后做client也很方便,請求發過去之后返回來的就是標準的json格式數據,同樣的解析方法,每個不同的應用就按照不同的格式處理下即可,和web等模塊交互也很方便,這可算是額外的好處了。

             

            總之,雖然json格式存儲效率和解析效率跟二進制方式還差半個量級到一個量級,但合理使用還是可以的,特別是跟xml相比優勢很明顯,權衡使用吧,當然追求極致效率可能還是用pb之類的更合適一些,或者自己設計tlv格式。

             

            posted @ 2011-01-11 13:33 袁斌 閱讀(2539) | 評論 (3)編輯 收藏

            07年我寫了一篇文章叫《我的網絡模塊設計》,姑且叫那個為第一版吧,由于持續對網絡模塊進行改進,所以現在的實現和當時有很大改變,加上上層應用越來越多,又經過了幾年時間考驗,現在的實現方式比之前的更靈活更有效率,也因為最近看了一些人做網絡程序多年竟毫無建樹,一直要用別人寫的網絡模塊,所以有感而寫此文,為了使得此文不受上一篇《我的網絡模塊設計》的影響,我決定寫之前不看原來的文章,所以此文跟原文那篇文章可能沒有太多相似性。
             一個基本的網絡模塊,無非就是管理N個連接,快速處理每個連接的收發數據、消息等,所謂好的網路模塊,無非就是穩定、高效、靈活,下面分幾部分來寫:
             一、 連接管理
             之所以首先寫連接管理,是因為連接管理是核心,也是最難的地方,我寫第一個網絡庫之前,搜索過很多當時可以找到的例子工程,當時幾乎找不到可穩定運行的工程,當然更找不到好的,于是摸索前進,期間對連接管理使用了各種方法,從最早一個cs(臨界區CriticalSection,我簡稱cs),recv send都用這個cs,到后來send用一個cs,recv用一個cs,用多個的時候還出過錯,最后使用一個cs+一個原子值ref管理一個連接,每個連接send的時候用cs,recv的時候用ref,如果該連接的消息要跨線程異步執行,也使用ref,如此較簡單的解決了連接管理的問題。
             同樣使用生存期管理方法,也有人用智能指針,雖然原理和我直接操縱生存期一樣,但實現方法畢竟不同,不過我為了讓實現依賴少一些沒有引入智能指針。
             當然我后來也發現很多人不是用這種方法,如有些人就id來管理連接,每個連接分個id,其他操作全部用id,每次對連接的調用先翻譯一下,如果id找得到映射目標就調用,否則就說明該連接不存在了,這種方法簡單只是不直接,多了個查找過程,另外查找的時候可能還需要全局鎖(這依賴于連接數據組織)。
             也有人使用一個線程管理連接,其他所有與該連接有關的生存期問題全部到該線程處理,這樣也是可行的,只是需要做一個較好的包裝,如果包裝好上層調用方便,如果包裝不好,可能上層調用就有一些約束。
             雖然各種方法都有人使用,但我一直選擇直接的生存期管理方法,其實內部實現的時候還是有很多優化措施的,減少了大量addref、release的調用,進一步提高了效率。
             二、 線程組
             我最初做網絡庫的時候還不是很清楚上層如何使用這個庫,后來在上面做了幾個應用之后慢慢有了更多想法,最近的網絡庫是設計了這么幾組線程:io線程組、同步線程組、異步線程組、時鐘線程組、log線程組,每組線程都可開可關,就算io線程組也是可關的,這只是為了整個庫更靈活適用性更廣泛,如只用同步線程組或異步線程組僅將這個線程組當一個消息隊列使用。
             Io線程組就是處理io收發的,listen recv send 以及解密解壓縮都是在這組線程,一般這組線程會開2個或2*cpu個。
             同步線程組,一般這組線程開1個,用來處理logic。
             異步線程組,這組線程根據需要開0個或n個,簡單應用無db等慢速操作的應用不開,有很多db等慢速操作的可以開很多個。
             時鐘線程組,一般不開或開1個。
             Log線程組,一般開1個,主要為了避免其他線程調用WriteLog的時候被磁盤io阻塞,所以弄了一個log線程。
             其實還有一個主線程,我的每組線程(包括主線程)都支持事件和定時器,io線程、同步線程、異步線程組、時鐘線程組、甚至log線程組都支持事件和定時器,到去年我還只是讓每組線程都支持事件,今年為了更好的使用時鐘我給每組線程設計了定時器,現在定時器線程組有點雞肋的味道,一般是用不上專門的定時器線程組,不過我還沒有將它刪掉,主要在我的設計里面,它和同步異步線程組一樣,都只是一組線程,如果必要的時候可以將它用作同步線程或者異步線程組,所以繼續保留了它的存在。
             這幾組線程之間都是可互發消息的,所以一個邏輯要異步到別的線程執行是非常方便的,只要調用一下PostXXEvent(TlsInfo *ptls, DWORD dwEvent, WPARAM wParam, LPARAM lParam);我憑借這個設計使得這套網絡庫幾乎可以適用上層各種應用,不管是非常簡單的網絡應用還是復雜的,一框打盡。對最簡單的,一個io線程搞定,其他線程全關,對于復雜的io線程+同步+異步+log全開。
             三、 內存池
             內存池其實沒有想象中的那么神秘,當然如果要讓一個網絡程序持續7*24小時穩定高效運行,內存池幾乎必不可少的,內存池的作用首先是減少內存碎片,其次是為了提高速度,我想這兩點很容易想明白的,關于內存池我之前寫了系列文章,可參考我的博客:
             
            《內存池之引言》 http://blog.csdn.net/oldworm/archive/2010/02/04/5288985.aspx
             《單線程內存池》 http://blog.csdn.net/oldworm/archive/2010/02/04/5289003.aspx
             《多線程內存池》 http://blog.csdn.net/oldworm/archive/2010/02/04/5289006.aspx
             《dlmalloc、nedmalloc》 http://blog.csdn.net/oldworm/archive/2010/02/04/5289010.aspx
             《線程關聯內存池》 http://blog.csdn.net/oldworm/archive/2010/02/04/5289015.aspx
             《線程關聯內存池再提速》 http://blog.csdn.net/oldworm/archive/2010/02/04/5289018.aspx
             
            四、 定時器
             關于定時器,上面講線程組的時候已經講過,我現在的設計是每個線程(包括主線程)都支持定時器,調用方法都是一樣的,回調函數形式也是一樣的,由于定時器放到各組線程里面,所以減少了線程之間的切換,提高了效率。
             關于定時器,可參考《定時器模塊改造》 http://blog.csdn.net/oldworm/archive/2010/09/11/5877425.aspx
             
            五、 包格式
             關于包格式可參考《常用cs程序自定義數據包描述》 http://blog.csdn.net/oldworm/archive/2010/03/24/5413013.aspx
             
            六、 Buffer
             之前的文章其實我一直沒有提過我的buffer,其實我的buffer設計是很靈活的,現在它和pool也是有些關聯的,我的poolset其實底下就是按照各種不同大小的buffer預設的尺寸。Buffer我設計為循環式,不允許回繞,包含
             Char *pbase 塊基址
             Char *pread 當前讀指針
             Char *pwrite 當前寫指針
             DWORD tag;
             Buffer *next;
             Capacity 總分配尺寸,上面分配的時候可能只是指定了19,但實際可能分配的是32個字節,所以內部用的時候要根據capacity來最大限度的利用緩沖區。
             Buffer分配還利用了一個技巧,事實上分配的時候是一次分配一個需要的大緩沖,前面為Buffer自身的數據,后面為數據部分,pbase指向數據部分,這樣處理減少了一次分配,我估計很多人都在用這個技巧。
             Pwrite總是不會小于pread的,但pread可能和pbase不一樣,僅當后面空余空間不夠用的時候才可能會移動數據,否則數據不會移動。
             WSARecv的時候我是這么處理的,如果首次獲取了一個包的一部分,但buffer中還有足夠的空間放下包的剩余部分,我不會再分配一個buffer去recv,而是直接用原buffer指定一個合適的偏移和size去WSARecv,這樣可以最大限度的減少復制。
             剛才還有朋友問到我recv的層次組織,我的網絡庫里面是這樣組織的,OnRecv是個虛函數,最基礎的IocpClient的OnRecv只處理數據而不解析格式,IocpClientMsg就會認識默認的一種包格式,這個類的OnRecv會將m_recvbuf中的數據組織為msg,并盡可能的一次返回更多個msg,回調OnMsg函數,由上層決定該消息在哪個線程處理,這樣我認為是最靈活的,如果是個很小的server,可能直接就在io線程里面處理了,也可postevent到同步線程處理,亦可PostEvent到異步線程處理。
             
            七、 TLSINFO
             TlsInfo顧名思義就是每個線程關聯的一組數據,暫時我還沒有看到別人這么設計,也許我設計得有些復雜了,在這個數據里面有一些常用的和該線程相關的數據,如該線程的分配基、步長,用這兩個參數可讓每個線程制造出唯一序列,還有常用pool的地址,如tm_pool *p1k; tm_pool *p2k;… 這樣設計使得要分配的時候直接取tm_pool,最大限度的發揮了分配速度,還有一些常規參量long c; long d; DWORD a; DWORD b;… 這幾個值可理解為棧內值,其實為了減少上層調用復雜度的,如我將一個連接的包從io線程PostEvent到同步線程處理,PostEvent首參數就是tlsinfo,PostEvent會根據tlsinfo里面的一個內部值決定是不是要調用addref,因為我有個地方預增了2,所以大多數情況下在io發到其他線程的時候是無需調用addref的,提高了效率,tlsinfo里的其他一些值上層應用可使用,用在邏輯處理等情況下。
             
            八、 性能分析
             *nix下有很多知名的網絡庫,但在win下特別是使用iocp的庫里面,一直就沒有一個能作為基準的庫,即使asio也因為出來太晚不為大多數人熟悉而不能成為基準庫,libevent接iocp由于采用0 buffer模擬所以也沒有發揮出足夠的性能,對比spserver我比它快70%左右,我總在想要是微軟能將他那個iocp的例子寫得更好一點就好了,至少學的人有一個更高一點的基礎,而不至于讓http://www.codeproject.com/KB/IP/iocp_server_client.aspx這樣的垃圾代碼都能成為很多人的樣板。
             
            九、 雜談
             為了寫好一個win下穩定高效的網絡庫,我07年的時候幾乎搜遍了那個時間段之前所有能找到的iocp例子,還包括通過朋友等途徑看到的如snda等網絡庫,可惜真沒找到好的,大多數例子是只要多線程發起幾千個連接不斷發送數據馬上就死了,偶爾幾個不死的(包括snda的)只要隨機連接并斷開就會產生句柄泄漏,關閉所有連接之后句柄并不關閉等,也就是說這些例子連基本的生存期管理都沒搞定,能通過生存期管理并且不死的只有有限的幾個,可惜性能又太差,杯具啊。
             早年寫網絡庫的時候也加入了sodme在google上建的那個群,當時群還是很熱鬧的,可惜大多數人都是摸索,所以很多問題只是討論卻從無定論,沒有誰能說服別人,也沒有人可輕易被說服,要是現在或許有一些很有經驗的人,可惜那個群由于GFW現在雖能訪問也不大活躍了。
             最近看到有些寫網絡程序7年甚至更久的人還在用libevent、ace等感想很復雜,可悲的是那些人還沒意識到用一個庫和寫一個庫有多大的區別,可能那些人一輩子也認識不到寫一個庫比用一個庫難多少,那些人以為這些庫基本會用了,讓他自己去寫也基本是照這個模式,不會有什么突破,就無需自己動手了,悲哀啊。當然,要寫一個穩定的網絡庫需要耗費很多時間,特別是要寫一個能和知名庫性能接近或更好的庫,更是要費神費力,沒點耐心和持久力是不可能做好的。在中文領域隨便查什么稍有些名氣的代碼,總是能找到很多剖析類文章,可原創的東西總是很少,也不知道那些大俠怎么搞的,什么都能剖析可怎么總寫不出什么像樣的東西呢。
             其實本來沒有打算寫這篇文章,可能是看了陳碩的muduo才使得我有了寫出來的沖動,大概是受到他的開源鼓勵吧。
             謹以此文記錄本人最近3年對網絡模塊的修改并簡短總結。

             

            posted @ 2010-10-03 14:25 袁斌 閱讀(3264) | 評論 (5)編輯 收藏

            實用云計算環境簡述

             

            如今it領域沒聽說過云計算的絕對是out了,雖然大家都知道云計算,雖然很多高校很多專業都開設了云計算專業,雖然很多人都在討論云計算,雖然也有少數人走在了應用云計算的前列,然而,可悲的是,大多數人對云計算的認識僅限于amazongooglemicrosoftibm有能力架設云計算環境,其他公司都靠邊,甚至唯他們的云計算才叫云計算,別的企業根本不可能做云計算,各級政府部門最搞笑了,動不動花多少錢引進某某云計算環境,填補某某空白,多少cpu多少機器每秒多少萬億次計算,最終是不是一堆浪費電力的擺設也沒有人知道,也沒人去過問。

            略感欣慰的是,很多企業都在務實地部署自己的云計算環境,大如騰訊、淘寶、百度、小如我們這樣剛成立的小公司,其實要部署一個私有云計算環境并沒有那么難,以我個人的經驗來看,如果有一個精干的小團隊,幾個人一個月部署一個私有云計算環境是完全可能可行的。在我看來,所謂云計算就是分布式存儲+分布式計算,不局限于底下oswin還是*nix,也不局限于是局域網環境還是廣域網環境,也不管上面跑的是c++的程序還是javascript的程序,下面簡單介紹下我設計的一個即時查詢價格的云計算體系:

            我一直在win下開發,win用得非常熟練,所以我把云計算環境部署在windows之上,當然也考慮到windows的機器眾多,tasknode可輕易找到非常多的目標機器,我部署的云計算環境主要分兩類節點,jobservertasknodejobserver主管任務切割、任務調度,tasknode是計算節點。另外還有一些節點,jobowner可連接jobserver并提交任務,并可查詢該任務的執行情況,admin可連接jobserver查詢jobserver的狀態。

             

            其實這些上篇博客已經寫過,我再講的詳細一點,看具體的執行情況,首先jobownerjobserver提交package,這個package是一個zip文件,包含一組文件,jobowner提交package之后jobserver會根據約定的規則管理package,并在jobserver展開該package,如下:

             

             

            Jobowner連到jobserver之后,發出如下的命令到jobserver

            0x49 0x0 0x0 0x0 0x2 0x0 0xb 0x0 127.0.0.1 0x0 ppsget.dll 0x0

            {type:[0,1,2,3,4],rmax:5,wb:"pc",text:"諾基亞 e63"} 0x0

            上面是用我設計的一種混合顯示格式顯示的包數據,可以看到里面帶上了ppsget.dll,這就是指定包內部名,其實還可以這樣ppsget.dll:getpage,如此一個dll就可支持多個IJobTask輸出,getpage只是獲得其中一個IJobTask接口(關于IJobTask接口參考上一篇云計算實踐2的文章)。具體命令是json格式,主要是為了方便信息傳輸和解析。Jobserver接收到該命令之后,調用ppsget.dllIJobTask接口中的split函數,將該任務分解,之后調度Tasknode執行,tasknode收到jobserver發過來的任務之后,檢查包名稱,如果缺少就會主動向jobserver要求發送相應的包,并進行部署,待部署完成之后從包獲取指定的IJobTask接口,執行該接口的map函數,將結果按照約定的格式發給jobserver,最后由jobserver調用IJobTask中的reduce函數進行打包,最后將結果發給jobowner并記錄相關Log

            上圖中還可看到一個HashCrackCloud.dll,這是另一個云計算環境下破解md5密碼的dll,這個上篇文章也寫了一下,這里就不詳述了。

             

            為使得tasknode可適應各種機器環境,我把tasknode設計為一個dll,該dll內部自己管理消息及任務執行,該dll可被加載到各種容器進程(如gui進程、console進程、service進程)等執行,看下我的tasknode和它的容器進程:

             

            這也算是我的得意設計吧,這樣設計的tasknodewindows系統下的確具有很高的靈活性。

            這樣的tasknode甚至可直接加載在jobserver進程,也可被任意win系列機器的任意進程加載參與運算,用主動加載或被動加載都很方便,極大的方便了云計算環境的部署,反正具體執行的任務都由package完成,tasknode只要按照約定的規則部署 package即可,所以這種云計算環境是非常輕量級又非常靈活的,開發一個新的任務只要做一個新的IJobTask即可,目前我這套體系除了沒有考慮太多安全性之外,這個云計算環境的實施還是非常容易的,實際上我們這個價格查詢的后臺云計算環境只用了不到2周的時間就開發完成。

            再看下jobserver記錄的每個joblog

             

            log中可很容易的分析出一個job每個task的執行情況,并可根據這些數據進行相應的優化處理。

            之所以把jobservertasknode以及package都寫出來,主要是為了表達一個看法,要實現一個簡單的云計算環境其實并不難,有經驗的團隊很容易就能做出來,參考下googlemap/reduce論文,按照自己的需要簡化實現,真理在實踐中,如果只是仰望googleamazon,那就真的是在云中霧里,另一個想要表達的就是云的形式是多種多樣的,并不一定amazonegoogle的云計算環境才是標準的,對實用派來說,形式都是次要的,實用才是關鍵的。

            posted @ 2010-10-03 14:23 袁斌 閱讀(1816) | 評論 (1)編輯 收藏

            僅列出標題  下一頁
            成人国内精品久久久久影院| 久久综合伊人77777麻豆| 精品无码久久久久久国产| 亚洲精品无码久久毛片| 精品视频久久久久| 久久免费国产精品| 色妞色综合久久夜夜| 亚洲人成无码www久久久| 久久精品国产99国产精品导航| 草草久久久无码国产专区| 久久久久久久97| .精品久久久麻豆国产精品| 久久综合综合久久97色| 久久天堂AV综合合色蜜桃网| 99久久夜色精品国产网站| 亚洲精品美女久久777777| 久久无码一区二区三区少妇| 亚洲国产精品无码久久久秋霞2| 狠狠色婷婷久久一区二区三区| 久久99国产精品久久久| 欧美日韩精品久久久久| 久久国产欧美日韩精品| 久久国产劲爆AV内射—百度| 成人国内精品久久久久一区| 九九精品久久久久久噜噜| 2021国内久久精品| 久久无码中文字幕东京热| 国产成人精品久久| 久久性生大片免费观看性| 久久福利片| 97久久精品无码一区二区| 久久一日本道色综合久久| 国产Av激情久久无码天堂| 久久99精品国产麻豆婷婷| 久久精品国产69国产精品亚洲| 国内精品久久久久伊人av| 国产免费久久久久久无码| 久久中文字幕视频、最近更新| 一本色道久久88精品综合| 亚洲国产成人精品91久久久| 国产精品久久一区二区三区|