SignalR Core尝鲜

要点

  • SignalR Core改用Microsoft.AspNetCore.Sockets,不再依赖HTTP。

  • 使用MessagePack序列化格式,支持二进制协议。

  • TypeScript客户端移除了第三方依赖包。

  • 支持WebSocket原生客户端,可以使用自己构建的客户端连接到SignalR服务器。

  • 伸缩方式更灵活,可以通过自己实现的方式进行横向扩展。

几个月前,SignalR Core团队发布了一个非官方版本的ASP.NET Core SignalR。为此,开发人员有机会了解其工作原理以及ASP.NET SignalR与Signal Core新架构之间的区别。 


SignalR Core中移除了哪些特性

通过对比两个版本的SignalR可以发现,新版本不再支持一些重要的特性。首先是移除了对jQuery和其他第三方类库的依赖,因为新版本的JavaScript客户端是使用TypeScript开发的。其次是自动连接后的消息重放功能,移除该功能主要是出于性能方面的考虑。服务器需要为每一个连接维护一个缓冲区,用于保存消息,以便后续重新发送。当客户端断开连接,可以尝试重新恢复连接,然后将未发送的消息发送给客户端。可以想象,如果有很多客户端断开连接,而且每个客户端都发送大量的消息,对于服务器来说是个很大的负担。另一个被SignalR团队移除特性是多Hub端点,所以,在新版本里,每个连接只有一个Hub。



新版本的SignalR Core不再支持横向扩展(Scale Out)模型,原因是MessageBus被当成了横向扩展的“万灵丹”,但它实际上只支持Azure Service Bus、Redis和SQL Server。在实际的协作场景当中(客户端到客户端),随着客户端和消息数量的增长,通过以上三种方式进行横向扩展会有瓶颈问题。

不过,我认为,移除横向扩展功能这一决定有点太过激进,因为在某些场景下,MessageBus仍然十分有用。例如,在将SignalR作为一个广播服务器时,它可以控制发送消息的数量。而在SignalR Core的alpha版本中,开发者可以根据实际情况选择是否进行横向扩展,如业务需求、系统约束或基础设施,这种设计更加“可插拔”。SignalR Core团队提供了一个使用Redis进行横向扩展的示例。其他扩展方式可能会被包含在SignalR Core的最终版中。

最后一个被移除的功能是多服务器间的双向复制(backplane),因为这个功能会在服务器场生成太多的流量。ASP.NET SignalR通过MessageBus在服务器间复制每一个消息,因为客户端无法直接连接到服务器场,而现在,SignalR使用粘性会话来避免在所有服务器间复制消息。这样一来,SignalR Core就可以知道哪个客户端连接到了哪台服务器上。

SignalR Core中增加了哪些新特性

现在让我们来看一下SignalR Core带来了哪些新的特性。首先是使用了二进制协议来发送和接收消息。在ASP.NET SignalR中只能使用JSON格式的文本来发送和接收消息,而现在则可以使用二进制协议,该二进制协议基于MessagePack序列化格式,比JSON更快、体积更小。

主机无关性是另一个非常重要的特性,有了这个特性,就可以移除对HTTP的依赖。现在,我们可以在HTTP或TCP之上使用SignalR。端点API也是非常重要的一个特性,它是基础的构建块,用于支持主机无关性。因为新版本是基于Microsoft.AspNetCore.Sockets这一底层的网络抽象层,所以可以直接使用Socket。这么说来,SignalR Hub其实也就是一个端点。

多格式也是一个很酷的特性,有了这个特性,我们可以处理任意格式的消息。我们可以使用多种不同的客户端连接到同一个端点,这些客户端可以使用不同的消息格式。也就是说,SignalR Core已经实现了消息的格式无关性。这个示例在同一个端点上使用了三种格式(JSON、PIPE和Protobuf)来读写消息,因为使用了自定义的处理器,可以无缝地处理各种格式的消息。正如之前提到的那样,可能是因为使用了Microsoft.AspNetCore.Sockets,从底层来看,消息都只是简单的二进制字节。

新版本还支持WebSocket原生客户端,所以开发者也可以使用除SignalR Web客户端之外的其他客户端。之前,开发者必须使用基于JavaScript的Web客户端连接到SignalR服务器上。现在,开发者可以自己开发客户端,充分利用浏览器API提供的优势。当然,开发者也可以使用最新的TypeScript客户端,因为TypeScript提供了很多有用的特性。另外,客户端是通过NPM包管理器进行发布的,这样依赖管理也就变得更简单了。

最后一点是,横向扩展变得更灵活,提供了更高的可扩展性。SignalR Core团队简化并改进了横向扩展模型,并提供了一个基于Redis的横向扩展示例,帮助开发者了解如何进行横向扩展。

去年9月14号,SignalR Core团队发布了第一个alpha版,10月9号发布了第二个alpha版,也就是SignalR Core 2.0官方预览版。现在,我们即将探讨这一版本中包含的主要变化。

在得知有新版本后,我在第一时间去拉取代码,并试着去构建最新的代码。不过,正如预期的那样,因为代码还在开发当中,无法立马构建成功。尽管如此,我们还是能够在第一时间看到正在发生的变更,这有助于我们了解为什么要做出这些变更。接下来,我将列出我在构建过程中遇到的问题,并告诉大家我做了哪些事情来修复这些问题。

要在项目中使用SignalR Core,必须引用Microsoft.AspNetCore.SignalR,最新版本是1.0.0-alpha2-final。

HubConnectionBuilder

在之前的版本中,如果要在服务器端连接到一个Hub,我们会使用HubConnection类,比如:

var connection = new HubConnection(new Uri(baseUrl), loggerFactory);

而现在,我们需要使用HubConnectionBuilder类(实现了Builder设计模式)来连接SignalR Core Hub,这也是第一个导致代码构建失败的变化。这一变化让建立连接变得更具可扩展性,不需要使用满是参数或带有null参数的构造函数。我很喜欢这个变化,因为它简化了建立连接的过程。

var connection = new HubConnectionBuilder().WithUrl(baseUrl).WithConsoleLogger().Build();

在服务器端处理连接

在之前的版本中,客户端在“On”方法中处理由SignalR Hub广播过来的数据,这个时候需要处理一大堆参数:

connection.On("UpdateCatalog", new[] { typeof(IEnumerable<Product>) }, data =>{var products = data[0] as List<Product>;foreach (var item in products){Console.WriteLine($"{item.name}: {item.quantity}");}});

可以看出,这个方法有点累赘,因为不管用不用得到方法里的参数,都必须指定这些参数和它们的类型,即使用不到,也要指定一个空数组。但问题是,处理器的参数是无类型的,所以,即使在数组中指定了类型,仍然需要遍历数组,对它们进行类型转换。

而新版本的SignalR Core提供了最新的泛型方法重载机制,通过这种方式指定参数类型后就不需要再进行类型转换。泛型方法对原始方法进行了包装,从而简化了开发者的工作。最终的代码更简单、可读性更好。

connection.On<List<Product>>("UpdateCatalog", products =>{// now, “products” parameter is a List<Product> type.foreach (var item in products){Console.WriteLine($"{item.name}: {item.quantity}");}});

命名约定

我发现Invoke方法名发生了变化(这个变化也导致代码构建失败):

await connection.Invoke("RegisterProduct", cts.Token, product, quanity);

这是一个异步方法,为了遵循命名约定,方法名被改成了InvokeAsync,方法参数的顺序也发生了改变,令牌参数被放在了最后:

await connection.InvokeAsync("RegisterProduct", product, quanity, cts.Token);

因为遵循了命名约定和标准,开发者在使用SignalR Core API(包括SignalR Core的开发者团队)时就更加直观,因为它带来了代码的统一性。例如,如果开发者在他们的IDE中使用了Intellisense,就可以提前知道这个方法是异步的。

另一个与命名约定有关的变化是MapEndpoint方法,这个方法被改成了MapEndPoint,遵循了Pascal的大小写风格。

之前:

app.UseSockets(routes =>{routes.MapEndpoint<MessagesEndPoint>("/message");});

现在:

app.UseSockets(routes =>{routes.MapEndPoint<MessagesEndPoint>("message");});

可以看到,现在不使用“/”符号了。MapHub方法也一样。不过,我们发现这里存在一个问题,这些方法没有使用PathString API。不过,在下一个版本中会继续使用“/”,与其他的.Net Core API保持一致。

命名变更

命名方面发生了很多变更,其中一个是与Connection类有关的ConnectionContext。ConnectionContext包含了与连接相关的信息,如元数据、通道等。

之前:

public override async Task OnConnectedAsync(Connection connection)

现在:

public override async Task OnConnectedAsync(ConnectionContext connection)

另一个命名方面的变更与ConnectionContext中的Transport有关。之前,用于管理输入和输出的属性分别叫作Input和Output,而现在它们被改为In和Out。

之前:

connection.Transport.Input.WaitToReadAsync()connection.Transport.Output.WriteAsync()

现在:

connection.Transport.In.WaitToReadAsync()connection.Transport.Out.WriteAsync()

TryRead和WriteAsync

TryRead和WriteAsync方法得到了简化。之前,它们接收一个Message对象作为参数。

之前:

Message message;if (connection.Transport.Input.TryRead(out message)){...}connection.Transport.Output.WriteAsync(new Message(payload, format, endOfMessage));

现在:

// message is byte[]if (connection.Transport.In.TryRead(out var message)){...}// payload is byte[]connection.Transport.Out.WriteAsync(payload);

现在他们使用字节数组作为参数,因为底层的Socket使用了Channel<byte[]>。SignalR Core团队认为,将字节数据移到上层可以让Socket层的逻辑更清晰。之前,SignalR Core团队在字节数据之上使用了一个底层的数据帧协议(不过WebSocket已经有数据帧,所以没有在WebSocket上使用该协议)。

因此,Microsoft.AspNetCore.Sockets层得到了“净化”,只允许端点处理二进制数据,而端点就可以使用任何一种协议,比如TCP或HTTP。

底层的数据帧协议是在Microsoft.AspNetCore.SignalR层实现的,所以消息类型、数据帧都是在实现了IHubProtocol接口的类中处理的,比如JsonHubProtocol和MessagPackHubProtocol。这种设计提供了一种可扩展的方式用于实现其他的Hub协议。

其他变更

我们可以直接通过NPM管理器来安装signalr-client,比如,我在package.json文件里将它作为客户端依赖:

{"version": "1.0.0","name": "asp.net","private": true,"dependencies": {"@aspnet/signalr-client": "^1.0.0-alpha2-final","jQuery.tabulator": "^1.12.0"}}

Visual Studio会在构建解决方案时自动安装这个包。当然,我们也可以使用.NET Core内置的新特性,它会自动把signalr-client文件拷贝到wwwroot目录,这样就不需要再使用gulp、grunt或其他任务执行器了。

[{"outputFileName": "wwwroot/lib/signalr/signalr-clientES5-1.0.0-alpha2-final.min.js","inputFiles": ["node_modules/@aspnet/signalr-client/dist/browser/signalr-clientES5-1.0.0-alpha2-final.min.js"],"minify": {"enabled": false}},{"outputFileName": "wwwroot/lib/signalr/signalr-client-1.0.0-alpha2-final.min.js","inputFiles": ["node_modules/@aspnet/signalr-client/dist/browser/signalr-client-1.0.0-alpha2-final.min.js"],"minify": {"enabled": false}}]

默认情况下,.NET Core启用minify选项,而我引用的文件已经被minify过,当它尝试再次minify这些文件时就会报错,于是我就把minify选项禁用了。

结论

以上就是我在升级到最新版SignalR Core时发现的一些变化。我把它们分享出来,让其他开发者也知道这些变更以及为什么要做出这些变更。我希望这些信息对大家有用,也鼓励大家在自己的项目中测试最新的SignalR Core。

我花了几个小时解决在构建新版本代码时遇到的问题,而查看代码和理解这些变更又额外花了我几个小时时间,不过这些都是值得的。

关于作者

Geovanny Alzate Sandoval 是一名来自哥伦比亚麦德林的系统工程师,他喜欢所有与软件开发、新技术、设计模式和软件架构相关的事物。他已经在该领域工作了十多年,做过开发者、技术负责人和软件架构师。他乐于向社区做贡献,喜欢在博客上写与微软新技术有关的东西。另外,他还是麦德林.NET开发者社区MDE.NET的联合组织者。


原文:http://www.infoq.com/cn/articles/signalr-alpha


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321884.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2016陕西省ACM 热身体B 种类并查集

Energy 发布时间: 2017年3月27日 11:31 最后更新: 2017年3月27日 18:30 时间限制: 1000ms 内存限制: 256M 描述 人类准备发射载人飞船前往火星。 飞船使用了一种特殊的反物质燃料来作为动力&#xff0c;在飞船的制造期间&#xff0c;同时人类也在从宇宙 的各个地方收集这…

kubernetes实践之运行aspnetcore webapi微服务

1、预备工作unbuntu 16.04 or abovedocker for linuxkubernetes for linux 集群环境2、使用vs2017创建一个web api应用程序&#xff0c;并打包镜像到本地。3、推送本地镜像到docker hub4、编写k8s资源配置文件(yml)hello-world-deployment.yml如下上面replicas部署两个副本实例…

使用.NET Core快速开发一个较正规的命令行应用程序

一般命令行程序包含什么&#xff1f;使用方式帮助信息子命令参数选项帮助信息帮助信息如上&#xff0c;介绍了命令的作用和参数、选项作用。这个是必不可少的。子命令一个应用程序打包了多个功能&#xff0c;这时候就可以使用子命令&#xff0c;比如 dotnet ef migrations&…

Window7 docker安装

一、下载docker toolbox docker-toolbox-windows-docker-toolbox安装包下载_开源镜像站-阿里云 -ce后缀的是免费的版本&#xff0c;其他是收费版本 二、安装 安装完成即可 三、启动docker 双击 Docker Quickstart Terminal启动 其他问题&#xff1a; 启动拉boot2docker镜像失…

aspnetcore.webapi实践k8s健康探测机制 - kubernetes

1、浅析k8s两种健康检查机制Liveness k8s通过liveness来探测微服务的存活性&#xff0c;判断什么时候该重启容器实现自愈。比如访问 Web 服务器时显示 500 内部错误&#xff0c;可能是系统超载&#xff0c;也可能是资源死锁&#xff0c;此时 httpd 进程并没有异常退出&#xff…

快速搭建CentOS+ASP.NET Core环境支持WebSocket

以前用python&#xff0c;go尝试在linux下做web服务&#xff0c;python没有强类型支持与高性能&#xff0c;go又没有很好的集成开发环境&#xff08;还有强迫症的语法&#xff09;&#xff0c;回头看了几次.net&#xff0c;都没有时间尝试&#xff0c;现终于实现了这些想法&…

来自后端的突袭? --开包即食的教程带你浅尝最新开源的C# Web引擎 Blazor

在今年年初, 恰逢新春佳节临近的时候. 微软给全球的C#开发者们, 着实的送上了一分惊喜. 微软正式开源Blazor &#xff0c;将.NET带回到浏览器.这个小惊喜, 迅速的在dotnet开发者中间传开了. 而就在昨天(2018年3月22日) Blazor发布了它的第一次Release. Blazor到底是个什么样的东…

dotnet watch+vs code提升asp.net core开发效率

在园子中&#xff0c;已经又前辈介绍过dotnet watch的用法&#xff0c;但是是基于asp.net core 1.0的较老版本来讲解的&#xff0c;在asp.net core 2.0的今天&#xff0c;部分用法已经不太一样&#xff0c;所以就再写一篇文章来介绍dotnet watch vs code来提升asp.net core开发…

ASP.NET Core + Docker + Jenkins + gogs + CentOS 从零开始搭建持续集成

没有采用gitlab&#xff0c;因为gitlab比较吃配置。也比较重&#xff0c;用不到那么多功能。采用go语言开发的gogs来代替。免费HTTPS证书安装Gogs (一个gitserver&#xff0c;类似于gitlab)安装DockerDocker配置加速器 一定要配置&#xff0c;用官方的源会让你体会到什么叫做绝…

使用CoreRT将.NET Core发布为Native应用程序

在上一篇文章《使用.NET Core快速开发一个较正规的命令行应用程序》中我们看到了使用自包含方式发布的.NET Core应用中包含了216个文件。我就写一个cat命令用得着这么动真格。。。这写出来的命令行还有人用吗&#xff1f;今天我们就来介绍一下MS的另一个开源项目CoreRT。用来解…

.NET Core 2.1预览版首次引入Global Tools

Global Tools是.NET Core 2.1预览版中其中一个初次出现的特性。Global Tools提供了一种方法&#xff0c;让开发人员编写的.NET Core应用可以打包成NuGet包交付。如果.NET Core运行在目标平台上&#xff0c;那么一个恰当打包的Global Tool就可以在那上面运行。JavaScript开发人员…

开源服务容错处理库Polly使用文档

在进入SOA之后&#xff0c;我们的代码从本地方法调用变成了跨机器的通信。任何一个新技术的引入都会为我们解决特定的问题&#xff0c;都会带来一些新的问题。比如网络故障、依赖服务崩溃、超时、服务器内存与CPU等其它问题。正是因为这些问题无法避免&#xff0c;所以我们在进…

大部分Intel hardware intrinsic 将在 .NET Core 2.1 中启用

编者注&#xff1a;SIMD via C# 引入了一套全新的机制&#xff0c;使得C# 以后可以像C/C 一样直接使用intrinsic functions 来直接操作Intel CPU 的大多数SIMD 指令了&#xff08;从SSE 到AVX2&#xff09;随着 .NET Core 2.1 发布的临近&#xff0c;上周CoreCLR 已经停止向mas…

运动员最佳配对问题

西安交大 软件53 蔡少斐 题号&#xff1a;6_5 题目叙述&#xff1a; 羽毛球队有男女运动员各n人。 给定2个nn矩阵P和Q。P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势&#xff1b;Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势。 由于技术配合…

TensorflowSharp 简单使用与KNN识别MNIST流程

机器学习是时下非常流行的话题&#xff0c;而Tensorflow是机器学习中最有名的工具包。TensorflowSharp是Tensorflow的C#语言表述。本文会对TensorflowSharp的使用进行一个简单的介绍。本文会先介绍Tensorflow的一些基本概念&#xff0c;然后实现一些基本操作例如数字相加等运算…

刷题bingo挑战赛1

前言 为了提高做题效率&#xff0c;最近发现了个玩bingo的好网站 https://bingosync.com 然后就有了这场bingobingobingo赛。 正题 生成代码 [ {"name":"P2638"},{"name":"P4265"},{"name":"P2331"},{"n…

ASP.NET Core Web 支付功能接入 微信-扫码支付篇

这篇文章将介绍ASP.NET Core中使用 开源项目 Payment&#xff0c;实现接入微信-扫码支付及异步通知功能。开发环境&#xff1a;Win 10 x64、VS2017 15.6.4、.NET Core SDK 2.1.101、.NET Core Runtime 2.0.61.新建"ASP.NET Core Web 应用程序"项目&#xff0c;我将它…

14、java中的集合(1)

1、为什么使用集合 面向对象语言使用对象体现事物&#xff0c;存储对象可以使用数组&#xff0c;但是数组的长度是固定的&#xff0c;存储的对象类型单一&#xff0c;不适用需求的变化&#xff0c;所以提供了集合。 2、集合和数组的区别 1&#xff09;数组长度定义之后不能改…

Microsoft AI - Custom Vision in C#

概述前面一篇 Microsoft AI - Custom Vision 中&#xff0c;我们介绍了 Azure 认知服务中的自定义影像服务&#xff1a;Custom Vision&#xff0c;也介绍了如果通过这个在线服务&#xff0c;可视化的完成项目创建、数据集上传和标注、模型训练、模型评估和测试。我们也提到&…

Unity引擎及编辑器C#源代码发布

3月23日我们在GitHub上发布了Unity引擎和编辑器的C#源代码&#xff0c;仅供Unity学习参考使用。为何如此决定为了了解或改进自己的Unity项目&#xff0c;一直以来有用户对Unity .NET程序集反汇编&#xff0c;我们的服务条款明确允许这样做。但反汇编有二大缺点&#xff1a;尽管…