對於一些基於TCP Socket的大型C/S應用來講,能進行跨服務器通訊多是一個繞不開的功能性需求。出現這種需求的場景相似於下面描述的這種狀況。html
假設,咱們一臺TCP應用服務器能同時承載10000人同時在線,而同時在線用戶數量一般爲5萬多,那可想而知,咱們須要部署6臺TCP應用服務器來分擔這些負載。再假設,咱們的應用中,任意的兩個客戶端都有可能須要互發消息(好比,傳送文件),這時問題就來了 -- 由於要互發消息的這兩個客戶端鏈接的多是不一樣的服務器。api
如何解決了?這就須要引入羣集平臺的概念。羣集平臺中有一個應用羣集管理服務器ACMS能夠將全部的TCP應用服務器管理起來,而且能在它們之間轉發消息。這樣,即便位於不一樣的TCP應用服務器上的客戶端之間也能夠相互發送消息了。結構模型簡化後以下所示:服務器
以上圖爲例,兩個客戶端Client01與Client02分別連上不一樣的應用服務器AS01和AS02,咱們假設因爲路由器的緣由(好比兩個路由器的NAT類型都是Symmetric),Client01與Client02之間的P2P通道沒有創建成功。此時,若是Client01與Client02之間要相互溝通訊息,那麼信息就會通過ACMS中轉。好比Client01要發信息給Client02,信息通過的路線將會是:Client01 => AS01 => ACMS => AS02 => Client02。 app
能簡單地實現這種模型嗎?而且讓這種跨服務器通訊對於客戶端而言是透明的?固然,基於ESPlatform羣集平臺,咱們很容易作到這一點。 本文咱們就實現一個這樣的demo。咱們以前有個老的簡單的IM的Demo,它演示了客戶端與服務器、以及客戶端與客戶端之間的基本通訊功能。只不過,在那個Demo中,相互通訊的客戶端連上的是同一個服務端。本文的Demo就是在那個老Demo的基礎上來進行升級,使得位於不一樣服務器上的兩個客戶端之間也能夠相互通訊。負載均衡
一.Demo項目結構tcp
本Demo總共包含4個項目。ide
1.ESPlatform.ACMServer:這個是基於ESPlatform的應用羣集服務器ACMS。函數
2.ESPlatform.SimpleDemo.Core:用於定義公共的信息類型、通訊協議。this
3.ESPlatform.SimpleDemo.Server:Demo的服務端。spa
4.ESPlatform.SimpleDemo.Client:Demo的客戶端。
二.應用羣集管理服務器ACMS
咱們不須要對ACMS進行任何修改,只須要關注配置文件中TransferPort和Remoting端口的值。
<configuration> <appSettings> <!--應用羣集中的服務器分配策略--> <add key="ServerAssignedPolicy" value="MinUserCount"/> <!--用於在AS之間轉發消息的Port--> <add key="TransferPort" value="12000"/> </appSettings> <system.runtime.remoting> <application> <channels> <!--提供IPlatformCustomizeService和IClusterControlService Remoting服務的Port--> <channel ref="tcp" port="11000" > <serverProviders> <provider ref="wsdl" /> <formatter ref="soap" typeFilterLevel="Full" /> <formatter ref="binary" typeFilterLevel="Full" /> </serverProviders> <clientProviders> <formatter ref="binary" /> </clientProviders> </channel> </channels> </application> </system.runtime.remoting> </configuration>
三.Demo服務端
在升級老的Demo時,首先須要添加ESPlatform.dll的引用,而後,使用ESPlatform.dll程序集中的ESPlatform.Rapid.RapidServerEngine替代ESPlus.Rapid.RapidServerEngine,並在構造函數中指定:當前服務端實例的ID、ACMS的IP地址及其TransferPort和Remoting端口。
//使用簡單的好友管理器,假設全部在線用戶都是好友。(僅僅用於demo) ESPlatform.Server.DefaultFriendsManager friendManager = new ESPlatform.Server.DefaultFriendsManager(); this.engine = new ESPlatform.Rapid.RapidServerEngine(int.Parse(this.textBox_serverID.Text), this.textBox_acmsIP.Text, int.Parse(this.textBox_acmsPort.Text) ,int.Parse(this.textBox_transferPort.Text)); this.engine.FriendsManager = friendManager; this.engine.Initialize(int.Parse(this.textBox_serverPort.Text), new CustomizeHandler(), new BasicHandler()); friendManager.PlatformUserManager = this.engine.PlatformUserManager;
其它的部分與老Demo徹底一致。
四.Demo客戶端
相對於老的Demo而言,客戶端的修改很是小,只是將配置文件中的服務器的IP和端口移到了登陸界面上,這樣方便指定要鏈接的服務端的地址。除此以外,沒有其它變化,甚至,客戶端的項目都不須要引用ESPlatform.dll。
五.運行Demo
1.啓動應用羣集管理服務器ACMS。
2.啓動第一個服務端,ServerID指定爲0,監聽6000端口。
3.啓動第二個服務端,ServerID指定爲1,監聽6001端口。
4.啓動第一個客戶端,鏈接ServerID爲0的服務端。
5.啓動第二個客戶端,鏈接ServerID爲1的服務端。
6.兩個客戶端之間能夠相互對話了。
(在正式的應用場景中,ACMS、兩個服務端、兩個客戶端 能夠部署在不一樣的機器器上)
下圖是Demo運行起來的效果:
題外話:從上圖中能夠看到,ACMS實時知道每臺應用服務器的在線人數、CPU利用率、內存利用率等信息,基於這些信息,咱們能夠輕鬆實現簡單的負載均衡的機制 -- 好比,黨有一個新的客戶端要登陸時,咱們能夠指派它去鏈接那個在線人數最少的應用服務器,或者,CPU利用率最低的應用服務器。
六.Demo下載