(一)Socket服務(wù)器整體架構(gòu)概述
2010-10-28 16:50 by 田志良, 4613 visits, 收藏, 編輯Socket服務(wù)器主要用于提供高效、穩(wěn)定的數(shù)據(jù)處理、消息轉(zhuǎn)發(fā)等服務(wù),它直接決定了前臺(tái)應(yīng)用程序的性能。我們先從整體上認(rèn)識(shí)一下Socket服務(wù)器,Socket服務(wù)器從架構(gòu)上一般分為:網(wǎng)絡(luò)層、業(yè)務(wù)邏輯層、會(huì)話層、數(shù)據(jù)訪問層,如圖:
(圖1)
(一) 網(wǎng)絡(luò)層
網(wǎng)絡(luò)層主要用于偵聽socket連接、創(chuàng)建socket、接受消息、發(fā)送消息、關(guān)閉連接。作為socket通信服務(wù)器,網(wǎng)絡(luò)層的性能相當(dāng)重要,所以我們?cè)谠O(shè)計(jì)網(wǎng)絡(luò)層時(shí),要著重在以下幾方面獲得突破:最大連接數(shù)、最大并發(fā)數(shù)、秒處理消息數(shù)。如何突破呢?下面我為大家介紹幾種網(wǎng)絡(luò)層常用到的一些技術(shù)和技巧(具體實(shí)現(xiàn),我將在博文中逐一具體闡述):
1)Buffer管理
每一個(gè)SocketAsyncEventArgs對(duì)象(以下簡(jiǎn)稱SAEA)在內(nèi)存中都有其對(duì)應(yīng)的緩存空間,如果不對(duì)這些緩存空間進(jìn)行同一管理,當(dāng)SAEA對(duì)象逐漸增多時(shí),這些SAEA對(duì)象的緩存空間會(huì)越來越大,它們?cè)谙到y(tǒng)內(nèi)存中不是連續(xù)的,造成很多內(nèi)存碎片,而且這些緩存不能重復(fù)利用,當(dāng)創(chuàng)建、銷毀SAEA對(duì)象時(shí),造成CPU很多額外消耗,影響服務(wù)器性能。面對(duì)這問題如何解決呢?用Buffer池管理!
2)雙工通信
Socket服務(wù)器提高通信效率是一個(gè)永恒的話題,提高通信效率有很多種方法,雙工通信就是其中之一。一個(gè)SAEA對(duì)象在同一時(shí)刻只能用來接收數(shù)據(jù)或發(fā)送數(shù)據(jù),有人想,如果一個(gè)SAEA對(duì)象在同一時(shí)刻既能發(fā)送數(shù)據(jù)又能接受數(shù)據(jù),那肯定會(huì)提高socket通信效率。恩,很有想法!可是你能讓你的頭在同一時(shí)刻既往左轉(zhuǎn)又往右轉(zhuǎn)嗎?答案是不行的,那如何實(shí)現(xiàn)雙工通信呢?既然一個(gè)SAEA對(duì)象在同一時(shí)刻只能做一件事,那我自定義DuplexSAEA對(duì)象,在該對(duì)象中封裝兩個(gè)SAEA,一個(gè)用于接受,一個(gè)用于發(fā)送,問題不就解決了嗎。
3)poolOfAcceptEventArgs
poolOfAcceptEventArgs是個(gè)什么東西?它不是個(gè)東西,是一個(gè)容器,一個(gè)容納AcceptSAEA對(duì)象的容器。給你兩個(gè)socket服務(wù)器,你能很快判別兩個(gè)服務(wù)器性能的優(yōu)異嗎?很簡(jiǎn)單,你瞬間向一臺(tái)服務(wù)器打入5、6萬的連接,看看會(huì)不會(huì)都連上,如果都連上,說明這臺(tái)socket服務(wù)器的并發(fā)處理連接的能力還是不錯(cuò)的。那如何提高socket服務(wù)器的并發(fā)連接能力呢?答案:poolOfAcceptEventArgs!
4)消息隊(duì)列調(diào)度器
消息隊(duì)列調(diào)度器主要分為兩種:接受消息隊(duì)列、發(fā)送消息隊(duì)列。為什么要用消息隊(duì)列呢?主要是提高socket服務(wù)器的吞吐量。首先我們定義一個(gè)隊(duì)列Queue,然后編寫N個(gè)調(diào)度器,不斷從隊(duì)列中調(diào)度消息,接受隊(duì)列調(diào)度器用于將消息拋至業(yè)務(wù)邏輯層處理,發(fā)送隊(duì)列調(diào)度器用于調(diào)用網(wǎng)絡(luò)層發(fā)送消息接口,向指定端口發(fā)送數(shù)據(jù)。
5)心跳掃描
有一個(gè)困惑:客戶端連接socket服務(wù)器,連接沒有斷開,但客戶端掛了,這樣這條連接在socket服務(wù)器中就成了釘子戶,落地生根不走了!一個(gè)釘子戶還可以忍受,千千萬萬個(gè)呢?那就崩潰了!怎樣解決這個(gè)問題呢?定時(shí)掃描每條連接,如果該條連接在超時(shí)時(shí)間內(nèi)沒有IO響應(yīng),則關(guān)閉它。
6)粘包
服務(wù)器在接受消息包時(shí),如果兩個(gè)數(shù)據(jù)包同時(shí)被你服務(wù)器收了怎么辦?你會(huì)把他當(dāng)成一個(gè)數(shù)據(jù)包嗎?如果一個(gè)數(shù)據(jù)包斷了,分成兩次被你服務(wù)器收了,你會(huì)把他們拼接起來嗎?這些就是粘包了,怎么解決?正則表達(dá)式掃描!
7)多線程編程
Socket服務(wù)器的編程就是多線程編程,面對(duì)多線程,線程間怎樣同步、怎樣避免死鎖?多線程訪問公共資源如何處理,在下面的博文中,我將會(huì)為大家具體闡述。
(二) 業(yè)務(wù)邏輯層
網(wǎng)絡(luò)層將解包后的消息包拋至業(yè)務(wù)邏輯層,業(yè)務(wù)邏輯層收到消息包后,解析消息類型,然后轉(zhuǎn)入相應(yīng)的處理流程處理。
網(wǎng)絡(luò)層應(yīng)提供發(fā)送消息的接口供業(yè)務(wù)邏輯層調(diào)用,因?yàn)榫W(wǎng)絡(luò)層不會(huì)主動(dòng)發(fā)送消息,發(fā)送消息的操作是由業(yè)務(wù)邏輯層來控制的,所以業(yè)務(wù)邏輯層應(yīng)根據(jù)具體的業(yè)務(wù)應(yīng)用,封裝不同功能的發(fā)送消息的方法。
(三) 會(huì)話層
會(huì)話層主要用于記錄在線用戶信息,該層隸屬于業(yè)務(wù)邏輯層。既然隸屬于業(yè)務(wù)邏輯層,那為什么還要獨(dú)立出來呢?這主要為以后分布式開發(fā)拓展用,試想,一臺(tái)服務(wù)器最大能支持多少人同時(shí)在線?中國有多少人?如果1億人同時(shí)在線,你一臺(tái)服務(wù)器能支持得了嗎?答案肯定是否定的,所以要分布式開發(fā)。分布式開發(fā)涉及到用戶信息同步的問題,所以會(huì)話層就要獨(dú)立出來了。
(四) 數(shù)據(jù)訪問層
數(shù)據(jù)庫執(zhí)行效率是整個(gè)socket服務(wù)器的瓶頸?為什么呢?舉個(gè)例子:假設(shè)我們的socket服務(wù)器的秒處理消息的條數(shù)為3000,每處理一條消息都會(huì)保存歷史記錄,那么,如果數(shù)據(jù)訪問層不想拖網(wǎng)絡(luò)層的后腿,那么他的執(zhí)行sql語句的效率也必須達(dá)到每秒3000!如果socket服務(wù)器和數(shù)據(jù)庫服務(wù)器部署在同一網(wǎng)段上,這個(gè)速度是沒有問題的,但如果數(shù)據(jù)庫服務(wù)器部署在外網(wǎng)呢?你的sql語句的執(zhí)行效率能達(dá)到那么高嗎?很困難!
再思考一個(gè)問題:如果網(wǎng)絡(luò)層執(zhí)行線程和數(shù)據(jù)庫執(zhí)行線程是同一個(gè)線程,那么網(wǎng)絡(luò)層的處理必須等待數(shù)據(jù)庫執(zhí)行完畢后,才能進(jìn)行!如果數(shù)據(jù)庫執(zhí)行效率比較慢,那對(duì)整個(gè)socket服務(wù)器將是一個(gè)毀滅性的打擊。
那么怎樣將數(shù)據(jù)訪問層與網(wǎng)絡(luò)層分離,讓他們互不影響?如何提高數(shù)據(jù)庫執(zhí)行效率,讓網(wǎng)絡(luò)層的處理速度和數(shù)據(jù)訪問層的處理速度達(dá)到一個(gè)平衡?答案:連接池+sql調(diào)度器+主從數(shù)據(jù)庫。
Socket服務(wù)器的整體架構(gòu)就為大家介紹到這里,下面我將會(huì)為大家具體闡述各個(gè)技術(shù)的實(shí)現(xiàn)。
#1樓 BenBen789 2010-10-28 17:02
分析幾乎涉及了Socket的方方面面,期待你的精彩后文。。。#2樓 何必 2010-10-28 17:14
很想好好學(xué)學(xué)socket 期待精彩后文#3樓 田戶名 2010-10-28 17:29
good#4樓 阿瑞|www.16hi.com 2010-10-28 17:47
飄過 關(guān)注一下#5樓 溫景良(Jason) 2010-10-28 18:00
最后那個(gè)才是我關(guān)心的#6樓 zhenjing 2010-10-28 20:21
到目前為止,從沒見過通用的服務(wù)器架構(gòu),總是因背景不同而不同#7樓 onlyfew 2010-10-28 20:44
拭目以待#8樓 hhshuai 2010-10-28 22:26
拭目以待#9樓 clound 2010-10-28 23:00
LZ 繼續(xù),哈哈#10樓 wufm 2010-10-29 09:25
期待#11樓 張磊(Rey) 2010-10-29 10:33
精彩,LZ繼續(xù)#12樓 詩雨流蘇飄 2010-10-29 11:34
good!不錯(cuò),頂!#13樓 ToBin 2010-10-29 12:30
灰常期待,不知道是不是.net底下的#14樓 Sylvester 2010-10-29 13:41
正好需要,贊一個(gè)。#15樓 liveshow021_jxb 2010-10-29 14:46
學(xué)習(xí)一記,一直想加強(qiáng)這方面的能力#16樓 愛在兩腿間 2010-10-31 17:59
期待你的分享#17樓 小羅 2010-11-11 10:24
樓主, 很期待你的博文. 個(gè)人愛好和工作都設(shè)計(jì)到這一塊.#18樓 大頭豬 2010-11-11 13:42
我剛剛開始學(xué)習(xí)有關(guān)socket通訊的技巧,非常期待樓主下一篇博文。呵呵,俺就天天關(guān)注啦#19樓 ToBin 2010-11-25 17:34
博主,你這文章出了很久了也沒出下面的文章,天天看RSS都沒有,實(shí)在等的蛋蛋疼了上來問問博主,啥時(shí)候能出下文啊。。。#20樓 qiuqingpo 2010-11-29 10:23
樓主.你把你的精彩講述出一本書吧.我第一個(gè)去買!期待下下...#21樓 ToBin 2010-11-29 18:01
文中提到"那我自定義DuplexSAEA對(duì)象,在該對(duì)象中封裝兩個(gè)SAEA,一個(gè)用于接受,一個(gè)用于發(fā)送,問題不就解決了嗎"有個(gè)問題,雖然用了兩個(gè)saea對(duì)象,但都是使用的一個(gè)socket連接啊,能同時(shí)即接受又發(fā)送嘛 ?
#22樓 sofakeer 2010-12-01 14:56
老大 期待你的這個(gè)系列。。。。。關(guān)注中。。
#23樓 sofakeer 2010-12-09 20:52
老大 啥時(shí)候 繼續(xù)寫??!期待死我了!
我要。。。。。看!
呵呵
#24樓 彭杰斌 2010-12-24 11:09
看到樓主的開篇,眼前一亮,期待后續(xù)大作。#25樓 o﹎Lin゛ 2011-07-08 09:00
不錯(cuò),,#26樓 海市蜃樓 2011-11-02 22:48
學(xué)習(xí)了。。。#27樓 edwardxh 2011-11-16 09:59
剛剛接觸Socket通信知識(shí),對(duì)此問題也比較關(guān)心,不知志良兄是否分析一下?