SignalR: 为什么选择 Hub 与持久连接?

我最近一直在搜索和阅读 SignalR,虽然我看到了很多关于集线器和持久连接之间区别的解释,但是我还没有能够理解下一个层次,这就是为什么我会选择一种方法而不是另一种方法?

50809 次浏览

从我在 连接和集线器部分中看到的情况来看,Hubs 似乎提供了一个覆盖较低级别持久连接的主题系统。

以下是高票通过的评论:

部分正确。您还可以在持久连接中获取主题或组。最大的区别在于发送不同类型的消息。例如,您有不同类型的消息,并且希望发送不同类型的有效负载。对于持久连接,您必须将消息类型嵌入到负载中(参见原始示例) ,但是集线器允许您通过连接执行 RPC (允许您从服务器和从服务器到客户机调用客户机上的方法)。另一个大问题是模型绑定。集线器允许您将强类型参数传递给方法。

文档中使用的示例使用了聊天室的比喻,其中用户可以加入一个特定的房间,然后只能从同一个房间中的其他用户那里获取消息。通常,代码订阅一个主题,然后只获取发布到该主题的消息。通过持久连接,您可以获得所有消息。

您可以轻松地在持久连接之上构建自己的主题系统,但是在本例中,SignalR 团队已经为您完成了这项工作。

有两种使用 SignalR 的方法: 你可以通过覆盖它的 PersistentConnection类来在低层访问它,这样你就可以对它有很大的控制权; 或者你可以让 SignalR 通过使用高层的“集线器”来完成所有繁重的工作。

持久连接是一个较低级别的 API,当连接打开或关闭时,您可以在更特定的时间执行操作,在大多数应用程序中,集线器是最佳选择

主要区别在于,您不能使用 PersisentConnection 进行 RPC,只能发送原始数据。所以不是像这样从服务器发送消息

Clients.All.addNewMessageToPage(name, message);

你必须发送一个带有 Connection.Broadcast()或者 Connection.Send()的对象,然后客户端必须决定如何处理它。例如,您可以发送这样一个对象:

Connection.Broadcast(new {
method: "addNewMessageToPage",
name: "Albert",
message: "Hello"
});

在客户身上,而不是简单地定义

yourHub.client.addNewMessageToPage = function(name, message) {
// things and stuff
};

你必须添加一个回调来处理所有传入的消息:

function addNewMessageToPage(name, message) {
// things and stuff
}


connection.received(function (data) {
var method = data.method;


window[method](data.name, data.message);
});

OnReceived方法中,您必须在服务器端执行同样的分派。您还必须反序列化那里的数据字符串,而不是像集线器方法那样接收强类型对象。

没有太多的理由选择持久连接而不是集线器。我注意到的一个原因是,可以通过持久连接到 发送保存的 JSON,但是不能使用集线器。在某些情况下,这可能是一个相关的性能优势。

除此之外,请看 文件的这段话:

选择沟通模式

大多数应用程序应该使用集线器 API 在下列情况下使用:

  • 需要指定实际发送的消息的格式。

  • 开发人员更喜欢使用消息传递和分派模型 而不是远程调用模型

  • 正在将使用消息传递模型的现有应用程序移植为使用 SignalR。

根据消息结构的不同,您还可以从使用 PersisentConnection 获得一些性能方面的好处。

您可能需要查看 SignalR 示例,特别是 这个。

在比较这两者时,需要考虑三个主要因素:

  • 消息格式
  • 沟通模式
  • 信号 R 定制

对于 Hubs 消息格式化,基本上是由您来处理的,但对于持久连接,消息是原始的,并且已经来回进行了标记化和解析。如果消息大小很重要,那么还要注意,持久连接的有效负载要比集线器的有效负载小得多。

在通信模型中,持久连接基本上具有发送和接收消息的功能,而集线器采用 远程过程调用远程过程调用模型,每个需求具有唯一的功能。

当涉及到定制时,由于持久连接的级别较低,它们可能会给您更多的定制控制权。