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或以上版本的支持(精简版除外)。
配置数据库
- 打开SQL Server管理器,创建新的数据库SignalR
- 使用一下命令检查数据库是否支持Service Broker
SELECT [name], [service_broker_guid], [is_broker_enabled] FROM [master].[sys].[databases]
- 如果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服务器,但是他们之间的消息同步了。

SignalR学习笔记(五) 横向扩展之SQL Server的更多相关文章
- Sharepoint2013商务智能学习笔记之Excel Service展示Sql Server数据Demo(五)
第一步,打开Excel新建空白工作簿 第二步,使用Excel连接sql 数据库 第三步,画图 第四步 添加筛选器 最后效果如下: 第五步,将Excel上传到sharepoint任意文档库,并直接点击 ...
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- (转)Qt Model/View 学习笔记 (五)——View 类
Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(五) indigo computer vision
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- SignalR学习笔记(二)高并发应用
虽然SignalR借助Websocket提供了很强大的实时通讯能力,但是在有些实时通讯非常频繁的场景之下,如果使用不当,还是会导致服务器,甚至客户端浏览器崩溃. 以下是一个实时拖拽方块项目的优化过程 ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
- muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor
目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...
随机推荐
- SpringBoot简单入门
一.创建SpringBoot项目 1.创建maven项目,pom引入springboot父级启动器(starter)依赖: <?xml version="1.0" encod ...
- 源生API解析XML文档与dom4j解析XML文档
一.XML语言 XML是一种可扩展的标记语言,是一种强类型的语言,类似HTML(超文本标记语言,是一种弱类型的语言).XML是一种通用的数据交换格式(关系型数据库),综上所诉:XML可以传输数据,也可 ...
- Objective-C代码简写
NSNumber 所有的[NSNumber numberWith…:]方法都可以简写了: [NSNumber numberWithChar:‘X’] 简写为 @‘X’; [NSNumber num ...
- Spring保护方法
Spring保护方法 一.使用注解保护方法 1.@Secured 由Spring Security提供,首先需要启用基于注解的方法安全性: @EnableGlobalMethodSecurity(se ...
- nodejs, 阿里oss上传下载图片
const archiver = require('archiver')const send = require('koa-send')const oss = require('ali-oss').W ...
- [POJ1961]Period (KMP)
题意 求字符串s的最小循环元长度和循环次数 思路 s[1~i]满足循环元要len能整除i并且s[len+1~i]=s[1~i-len] 代码 #include<cstdio> #inclu ...
- VS Code 常用插件
1.Chinese (Simplified) Language Pack for Visual Studio Code VS Code软件汉化 2.Auto Close Ta ...
- Go语言基础之接口
Go语言基础之接口 接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节. 接口 接口介绍 在Go语言中接口(interface)是一种类型,一种抽象的类 ...
- 用Group by分组后,取每组的前3条记录,怎么取?
使用子查询进行查询 SELECT * FROM home_content a WHERE ( SELECT count(id) FROM home_content WHERE class_link = ...
- [Educational Round 13][Codeforces 678F. Lena and Queries]
题目连接:678F - Lena and Queries 题目大意:要求对一个点集实现二维点对的插入,删除,以及询问\(q\):求\(max(x\cdot q+y)\) 题解:对每个点集内的点\(P( ...