凡是帶有“池”的,比如數(shù)據(jù)庫(kù)連接池、對(duì)象池、緩沖區(qū)池(后面可以看到
IBuffPool
)等等,都是為了避免資源的反復(fù)創(chuàng)建
/
銷(xiāo)毀所帶來(lái)的開(kāi)銷(xiāo)。需要為哪些資源對(duì)象建立“池”了?這些資源對(duì)象通常符合下面幾個(gè)特性:
(1)
在應(yīng)用中需要反復(fù)的被創(chuàng)建
/
銷(xiāo)毀。
(2)
創(chuàng)建
/
銷(xiāo)毀的開(kāi)銷(xiāo)比較大
(3)
應(yīng)用中給定時(shí)刻,對(duì)該資源對(duì)象的數(shù)量要求比較大
(4)
資源對(duì)象最好是無(wú)狀態(tài)的(
Stateless
),這樣方便直接復(fù)用
AS(
回顧
)
將所有的功能服務(wù)請(qǐng)求轉(zhuǎn)發(fā)給為該
AS
提供服務(wù)的
FS
群中的一個(gè)(參見(jiàn)。。。),然后
FS
將請(qǐng)求交給對(duì)應(yīng)的功能插件處理。那么
AS
和
FS
之間的通信通過(guò)什么方式進(jìn)行了?可選的方式有
.netRemoting
、
WebService
、
Tcp/Udp
等。基于效率和準(zhǔn)確性的考慮,
WebService
和
Udp
是不大合適的。那么
TCP
和
.netRemoting
,到底選用哪個(gè)?我們知道
.netRemoting
底層也是基于
Tcp
或
Http
協(xié)議的,為了做到模擬本地方法調(diào)用的方式,
.NETRemoting
也做了很多轉(zhuǎn)換的操作(堆棧幀《=》消息),導(dǎo)致了一些開(kāi)銷(xiāo),而直接使用
Tcp
則可以避免,而且
AS
和
FS
之間的消息的格式是兼容的(主要是使用了完全相同的消息頭,這就夠了),也就是說(shuō)一條消息從客戶(hù)端發(fā)出,可以不需做任何轉(zhuǎn)換就直接被
FS
的功能插件處理(加密、壓縮不計(jì)在內(nèi))。
如你所想,
ESFramework
推薦的方式是
AS
和
FS
直接通過(guò)低層的
Tcp
進(jìn)行通信。為了避免
Tcp
連接不斷建立、銷(xiāo)毀所帶來(lái)的開(kāi)銷(xiāo),
AS
和
FS
通信前,可以建立
Tcp
連接池。本文就關(guān)注
Tcp
連接池的原理和實(shí)現(xiàn)。
Tcp
連接池中存放的是
Tcp
連接――即
NetworkStream
對(duì)象,當(dāng)應(yīng)用需要使用時(shí),就從
Tcp
連接池中租借“
Rent
”一條連接,用完后再歸還“
GiveBack
”給連接池。
從上面的定義 可以看到 TcpStreamPool 從兩個(gè)接口繼承: ITcpPool 和 ITcpStreamPool 。先看看 ITcpStreamPool 的定義:
2 /// ITCPStreamPooltcp連接池用于管理大量的TCP連接
3 /// 作者:朱偉sky.zhuwei@163.com
4 /// sky2005.02.24
5 /// </summary>
6 public interface ITcpStreamPool
7 {
8 int ServerID{ get ; set ;}
9 int StreamCount{ get ; set ;} // 期望連接總數(shù)
10 int ActiveConnectionCount{ get ;} // 實(shí)際可用的連接數(shù)
11 IPEndPointFsIpe{ get ; set ;} // 功能服務(wù)器的IPE
12 int ReconnectSpan{ get ; set ;} // 分鐘
13 bool IsActive{ get ;}
14
15 void ReConnect(); // 手動(dòng)重連
16 void Initialize();
17 void DisposeConnections(); // 釋放池中所有連接,可以通過(guò)ReConnect來(lái)重新建立連接
18 void SetStreamDamaged( int streamHashCode);
19
20 NetworkStreamRentTcpStream();
21 void GiveBackTcpStream( int streamHashCode); // 將tcp連接規(guī)還給連接池
22 }
AS 和每個(gè) FS 之間都有一個(gè)連接池,每個(gè)功能服務(wù)器的區(qū)分是通過(guò) ServerID 來(lái)的,所以連接池也有一個(gè) ServerID 屬性標(biāo)志了本連接池是與哪個(gè) FS 相連的。 ReconnectSpan 屬性表明連接池要支持重連機(jī)制,即當(dāng)連接池中的所有連接都斷開(kāi)后(可能是 FS 掉線引起的),連接池應(yīng)能定時(shí)重連 FS ,直至該池中的所有連接重新建立。
如果應(yīng)用從連接池 Rent 了一條連接,然后在使用的過(guò)程中該連接斷開(kāi)了,則應(yīng)用應(yīng)該調(diào)用連接池的 SetStreamDamaged 方法通知連接池該連接已不可用。 RentTcpStream 方法和 GiveBackTcpStream 方法是我們最常用的租借 / 歸還連接的方法了。
注意,很多方法的參數(shù)中有 streamHashCode 參數(shù),它是 NetworkStream 對(duì)象的 Hashcode ,系統(tǒng)中的每個(gè) NetworkStream 對(duì)象的 HashCode 是不同的,并且,它的 HashCode 在 NetworkStream 對(duì)象的整個(gè)生命期間不變,所以可以使用 HashCode 唯一標(biāo)志每個(gè)連接。
似乎,
ITcpStreamPool
接口已經(jīng)反映了一個(gè)連接池的所有東西,是的。那么
ITcpPool
接口又起什么作用了?現(xiàn)看看
ITcpPool
的樣子:
2 /// ITcpPool用于將一個(gè)TCP連接池和一組TCP連接池統(tǒng)一起來(lái)。這樣消息分派器只需使用ITcpPool接口即可。
3 /// zhuweisky
4 /// </summary>
5 public interface ITcpPool
6 {
7 RentStreamResultRentTcpStream( int poolTypeKey, int serviceKey, out NetworkStreamstream, out int serverID); // poolTypeKey表示某個(gè)城市,serviceKey表示某項(xiàng)服務(wù)
8 void GiveBackTcpStream( int streamHashCode, int serverID); // 將tcp連接規(guī)還給連接池
9 void SetStreamDamaged( int streamHashCode, int serverID); // poolKey如果不易保存,則此處簡(jiǎn)單的傳-1即可
10
11 event CallBackCountChangedActiveConnectionCountChanged;
12 event CallBackPoolStateChangedPoolStateChanged;
13 }
14
15 public delegate void CallBackCountChanged( int serverID, int activeConnCount);
16 public delegate void CallBackPoolStateChanged( int serverID, bool disconnected);
17
18 public enum RentStreamResult
19 {
20 Succeed,Busy,TheServiceNotExist
21 }
你可能已經(jīng)發(fā)現(xiàn), ITcpPool 中的所有元素在 ITcpStreamPool 接口中都可以找到對(duì)應(yīng)物,只是有些方法的參數(shù)變復(fù)雜了。這主要是因?yàn)? ITcpStreamPool 接口針對(duì)的是一個(gè)FS,而 ITcpPool可能是針對(duì)一個(gè)FS也可能是一組FS。當(dāng) ITcpPool背后是一組FS時(shí),就 需要參數(shù)ServerID來(lái)區(qū)分每一個(gè)FS。 我們知道, AS 和對(duì)應(yīng)的每個(gè) FS 之間都使用一個(gè) Tcp 連接池通信:

所有的這些連接池需要被管理起來(lái),
ESFramework
中的
ITcpPoolsManager
(
連接池管理器)組件實(shí)現(xiàn)了對(duì)多個(gè)
Tcp
連接池的管理。為了把連接池管理器和單個(gè)連接池統(tǒng)一起來(lái),使它們有相同的外部接口,所以引入了
ITcpPool
接口。
這樣做的好處是,在應(yīng)用中直接使用
ITcpPool
接口就可以了,而不用關(guān)心這個(gè)接口背后是一個(gè)“單個(gè)連接池”(對(duì)應(yīng)單個(gè)
FS
)還是由連接池管理器管理的“一組連接池”(對(duì)應(yīng)多個(gè)
FS
)。而且
ITcpPoolsManager
為我們的應(yīng)用進(jìn)行了很多復(fù)雜的管理,比如動(dòng)能服務(wù)器的調(diào)度(實(shí)現(xiàn)
FS
的負(fù)載均衡)、連接池的動(dòng)態(tài)添加
/
移除等。這些將在下文中介紹。
下一篇文章:ESFramework介紹之(11)-- Tcp連接池管理器
上一篇文章:
ESFramework介紹之(6)―― 基于C/S的4層架構(gòu)概述
轉(zhuǎn)到:
ESFramework 可復(fù)用的通信框架(序)
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
