通訊伺服器群集——跨伺服器通訊Demo(原始碼)

zhuweisky發表於2013-10-15

  對於一些基於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原始碼

 

 

 

 

相關文章