zoukankan      html  css  js  c++  java
  • 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服务器,但是他们之间的消息同步了。

  • 相关阅读:
    蝶恋花
    JVM解毒——JVM与Java体系结构
    超赞!IDEA 最新版本,支持免打扰和轻量模式!
    SpringBoot 结合 Spring Cache 操作 Redis 实现数据缓存
    神奇的 SQL 之 WHERE 条件的提取与应用
    终于放弃了单调的swagger-ui了,选择了这款神器—knife4j
    Git 高级用法,喜欢就拿去用
    既然有 HTTP 请求,为什么还要用 RPC 调用?
    SpringBoot和Spring到底有没有本质的不同?
    一条简单的更新语句,MySQL是如何加锁的?
  • 原文地址:https://www.cnblogs.com/lwqlun/p/9095094.html
Copyright © 2011-2022 走看看