天天看點

SignalR學習筆記(五) 橫向擴充之SQL Server

當一個Web應用程式達到一台伺服器能力限制,即請求處理數量限制之後,有2種解決方案:縱向擴充和橫向擴充。

  • 縱向擴充即用更強的伺服器(或虛拟機),或為目前的伺服器添加更多的記憶體,CPU等
  • 橫向擴充即添加多台伺服器或者虛拟機來做負載均衡 

縱向擴充的問題是,伺服器的配置更新的費用比較高,而且總有更新的極限,很容易就再次達到限制。而橫向擴充就沒有這個限制,不同的使用者可以被分流到不同的伺服器,進而解決負載問題

SignalR學習筆記(五) 橫向擴充之SQL Server

但是這樣的橫向解決方案,會有一個問題,即使用者被分流到不同SignalR伺服器之後, 不同伺服器上的使用者就沒有辦法同步消息。

以一個聊天室程式為例,可能使用者A,使用者B被分流到伺服器A, 使用者C被分流到伺服器B, 當使用者A發送普通廣播消息, 使用者B因為和使用者A分流到同一台伺服器,是以能收到這條消息,使用者C因為不在伺服器A上,是以就沒有辦法收到這條消息。

底闆(backplane)

Signal引入了一個底闆的概念來解決不同伺服器之間同步的問題。如果SignalR啟用底闆功能,每個應用執行個體發送消息的消息都會先傳輸到底闆,底闆會向所有連接配接的伺服器發送同步消息,每個SignalR執行個體會把接收到的消息儲存在記憶體中,然後同步給連接配接該執行個體的用戶端。這樣就解決了消息不同步的問題。

SignalR學習筆記(五) 橫向擴充之SQL Server

但是正因為有了底闆機制,與單伺服器SignalR應用相比,端到端通信和高并發應用的速度會減慢,同時發送的消息數量會減少,因為所有的用戶端消息都是高頻率的發送到SignalR伺服器,SignalR伺服器發送該消息到底闆,底闆再和所有的伺服器同步消息,最在才通知到所有的連接配接用戶端,是以對于這2種應用場景最适合還是單伺服器SignalR應用。

底闆最适合的是伺服器廣播,股市報價或者比賽文字直播就是最好的例子,因為所有的用戶端都是被動接受消息,伺服器端可以控制同時發送消息的數量。

SignalR預設支援的三種底闆

  • Azure Service Bus
  • Redis
  • SQL Server

SignalR使用SQL Server做橫向擴充

SignalR學習筆記(五) 橫向擴充之SQL Server

底闆功能需要SQL Server 2005或以上版本的支援(精簡版除外)。

配置資料庫

  1. 打開SQL Server管理器,建立新的資料庫SignalR
  2. 使用一下指令檢查資料庫是否支援Service Broker
SELECT [name], [service_broker_guid], [is_broker_enabled]

FROM [master].[sys].[databases]      
  1. 如果SignalR的is_broker_enabled标志是false, 請輸入以下指令啟用Service Broker
ALTER DATABASE YOUR_DATABASE SET ENABLE_BROKER      

Service Broker

Service Broker為SQL Server提供的原生的消息隊列功能,啟用Service Broker可以使底闆更有效率的更新同步消息。但是不啟用Service Broker, 底闆依然可以運作。

建立項目

參照學習筆記(三)的代碼,建立以下解決方案

SignalR學習筆記(五) 橫向擴充之SQL Server

ScaleoutSqlServer, ScaleoutSqlServer2與之前學習筆記(三)SignalRSelfHost代碼完全相同

ChatRoom和ChatRoom2與與之前學習筆記(三)ChatRoom的代碼完全相同

引入SQL Server底闆支援

打開Package Manage Console面闆,輸入以下指令, 分别對

Install-Package Microsoft.AspNet.SignalR.SqlServer

啟用SQL Server底闆

打開ScaleoutSqlServer和ScaleoutSqlServer2工程中的Program.cs

ScaleoutSqlServer

class Program

    {

        static void Main(string[] args)

        {

            using (WebApp.Start<Startup>("http://localhost:9021"))

            {

                Console.WriteLine("Server started.");

                Console.Read();

            }

        }

    }

 

    class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            // Any connection or hub wire up and configuration should go here

            string sqlConnectionString = "Server=.;Initial Catalog=SignalR; Integrated Security=true";

            GlobalHost.DependencyResolver.UseSqlServer(sqlConnectionString);

            app.UseCors(CorsOptions.AllowAll);

            app.MapSignalR();

        }

}      

ScaleoutSqlServer2

class Program

    {

        static void Main(string[] args)

        {

            using (WebApp.Start<Startup>("http://localhost:9032"))

            {

                Console.WriteLine("Server started.");

                Console.Read();

            }

        }

    }

 

    class Startup

    {

        public void Configuration(IAppBuilder app)

        {

            // Any connection or hub wire up and configuration should go here

            string sqlConnectionString = "Server=.;Initial Catalog=SignalR; Integrated Security=true";

            GlobalHost.DependencyResolver.UseSqlServer(sqlConnectionString);

            app.UseCors(CorsOptions.AllowAll);

            app.MapSignalR();

        }

}      

前台頁面連結不同的SignalR伺服器

修改ChatRoom, ChatRoom2中的ChatRoom.html

ChatRoom

<script src="Scripts/jquery.signalR-2.2.2.min.js"></script>

    <!--<script src="signalr/hubs"></script>-->

    <script src="http://localhost:9021/signalr/hubs"></script>

 

    <script type="text/javascript">

        $(function () {

 

            $.connection.hub.url = 'http://localhost:9021/signalr';      

ChatRoom2

<script src="Scripts/jquery.signalR-2.2.2.min.js"></script>

    <!--<script src="signalr/hubs"></script>-->

    <script src="http://localhost:9032/signalr/hubs"></script>

 

    <script type="text/javascript">

        $(function () {

 

            $.connection.hub.url = 'http://localhost:9032/signalr';      

最終效果

分别啟動2個SignalR伺服器, 并分别打開2個ChatRoom.html頁面。

雖然2個Web應用程式通路的是不同的SignalR伺服器,但是他們之間的消息同步了。

SignalR學習筆記(五) 橫向擴充之SQL Server