文章出處

  對于一些基于TCP Socket的大型C/S應用來說,能進行跨服務器通信可能是一個繞不開的功能性需求。出現這種需求的場景類似于下面描述的這種情況。

  假設,我們一臺TCP應用服務器能同時承載10000人同時在線,而同時在線用戶數量通常為5萬多,那可想而知,我們需要部署6臺TCP應用服務器來分擔這些負載。再假設,我們的應用中,任意的兩個客戶端都有可能需要互發消息(比如,傳送文件),這時問題就來了 -- 因為要互發消息的這兩個客戶端連接的可能是不同的服務器。

  如何解決了?這就需要引入群集平臺的概念。群集平臺中有一個應用群集管理服務器ACMS可以將所有的TCP應用服務器管理起來,并且能在它們之間轉發消息。這樣,即使位于不同的TCP應用服務器上的客戶端之間也可以相互發送消息了。結構模型簡化后如下所示:

    

  以上圖為例,兩個客戶端Client01與Client02分別連上不同的應用服務器AS01和AS02,我們假設由于路由器的原因(比如兩個路由器的NAT類型都是Symmetric),Client01與Client02之間的P2P通道沒有建立成功。此時,如果Client01與Client02之間要相互溝通信息,那么信息就會經過ACMS中轉。比如Client01要發信息給Client02,信息經過的路線將會是:Client01 => AS01 => ACMS => AS02 => Client02。 

  能簡單地實現這種模型嗎?并且讓這種跨服務器通信對于客戶端而言是透明的?當然,基于ESPlatform群集平臺,我們很容易做到這一點。 本文我們就實現一個這樣的demo。我們之前有個老的簡單的IM的Demo,它演示了客戶端與服務器、以及客戶端與客戶端之間的基本通信功能。只不過,在那個Demo中,相互通信的客戶端連上的是同一個服務端。本文的Demo就是在那個老Demo的基礎上來進行升級,使得位于不同服務器上的兩個客戶端之間也可以相互通信。

一.Demo項目結構

  本Demo總共包含4個項目。

1.ESPlatform.ACMServer:這個是基于ESPlatform的應用群集服務器ACMS。

2.ESPlatform.SimpleDemo.Core:用于定義公共的信息類型、通信協議。

3.ESPlatform.SimpleDemo.Server:Demo的服務端。

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下載

  群集、跨服務器通信Demo源碼

 

 

 

 


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()