Loading

SignalR学习笔记(五) 横向扩展之SQL Server

当一个Web应用程序达到一台服务器能力限制,即请求处理数量限制之后,有2种解决方案:纵向扩展和横向扩展。

  • 纵向扩展即用更强的服务器(或虚拟机),或为当前的服务器添加更多的内存,CPU等
  • 横向扩展即添加多台服务器或者虚拟机来做负载均衡 

纵向扩展的问题是,服务器的配置升级的费用比较高,而且总有升级的极限,很容易就再次达到限制。而横向扩展就没有这个限制,不同的用户可以被分流到不同的服务器,从而解决负载问题

 

 

 

但是这样的横向解决方案,会有一个问题,即用户被分流到不同SignalR服务器之后, 不同服务器上的用户就没有办法同步消息。

 

以一个聊天室程序为例,可能用户A,用户B被分流到服务器A, 用户C被分流到服务器B, 当用户A发送普通广播消息, 用户B因为和用户A分流到同一台服务器,所以能收到这条消息,用户C因为不在服务器A上,所以就没有办法收到这条消息。

 

底板(backplane)

 

Signal引入了一个底板的概念来解决不同服务器之间同步的问题。如果SignalR启用底板功能,每个应用实例发送消息的消息都会先传输到底板,底板会向所有连接的服务器发送同步消息,每个SignalR实例会把接收到的消息保存在内存中,然后同步给连接该实例的客户端。这样就解决了消息不同步的问题。

 

 

但是正因为有了底板机制,与单服务器SignalR应用相比,端到端通信和高并发应用的速度会减慢,同时发送的消息数量会减少,因为所有的客户端消息都是高频率的发送到SignalR服务器,SignalR服务器发送该消息到底板,底板再和所有的服务器同步消息,最在才通知到所有的连接客户端,所以对于这2种应用场景最适合还是单服务器SignalR应用。

 

底板最适合的是服务器广播,股市报价或者比赛文字直播就是最好的例子,因为所有的客户端都是被动接受消息,服务器端可以控制同时发送消息的数量。

 

SignalR默认支持的三种底板

  • Azure Service Bus
  • Redis
  • 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, 底板依然可以运作。

 

创建项目

参照学习笔记(三)的代码,创建以下解决方案

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服务器,但是他们之间的消息同步了。

 

posted @ 2017-06-12 08:13  LamondLu  阅读(570)  评论(0编辑  收藏  举报