3

我有一个使用 ajax 轮询从服务器获取股市更新的网页。我想改用 SignalR,但我无法理解它如何/是否会起作用。

好吧,这不是真正的股市更新,但类比有效。

我见过的 SignalR 示例向当前连接、所有连接或组发送消息。在我的示例中,库存更新发生在当前连接之外,因此没有“当前连接”之类的东西。并且用户的帐户与一些股票相关联,因此向所有连接或组发送股票通知也不起作用。我需要能够找到与某个 userId 关联的连接。

这是一个假代码示例:

foreach(var stock in StockService.GetStocksWithBigNews())
{
    var userIds = UserService.GetUserIdsThatCareAboutStock(stock);

    var connections = /* find connections associated with user ids */;

    foreach(var connection in connections)
    {
        connection.Send(...);
    }
}

在这个关于过滤连接的问题中,他们提到我可以将当​​前连接保留在内存中,但是(1)它不利于扩展,(2)它不利于多节点网站。这两点对我们当前的应用程序都至关重要。这让我觉得我必须向所有节点发送消息才能找到连接到每个节点的用户>>我的大脑在混乱中爆炸。

问题

如何为特定用户找到可扩展的连接?我在想这个错误的方式吗?

4

2 回答 2

6

我昨晚创建了一个小项目来学习这个。我使用了 1.0 alpha,它是直截了当的。我创建了一个集线器,并从那里开始工作:)

在我的项目中,我有 N 个计算单元(一些服务器处理工作),当它们启动时,它们会调用 ComputeUnitRegister。

await HubProxy.Invoke("ComputeUnitReqisted", _ComputeGuid);

每次他们做一些他们称之为的事情

HubProxy.Invoke("Running", _ComputeGuid);

其中 HubProxy 是:

HubConnection Hub = new HubConnection(RoleEnvironment.IsAvailable ?
                    RoleEnvironment.GetConfigurationSettingValue("SignalREndPoint"):
                    "http://taskqueue.cloudapp.net/");
IHubProxy HubProxy = Hub.CreateHubProxy("ComputeUnits"); 

我使用 RoleEnviroment.IsAvailable 是因为我现在可以将其作为 Azure Role、控制台应用程序或 .NET 4.5 中的任何内容运行。Hub 被放置在一个 MVC4 网站项目中,并像这样启动:

        GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(50);
        RouteTable.Routes.MapHubs();

public class ComputeUnits : Hub
{
     public Task Running(Guid MyGuid)
     {
         return Clients.Group(MyGuid.ToString()).ComputeUnitHeartBeat(MyGuid,
                DateTime.UtcNow.ToEpochMilliseconds());            
     }
     public Task ComputeUnitReqister(Guid MyGuid)
     {
         Groups.Add(Context.ConnectionId, "ComputeUnits").Wait(); 
         return Clients.Others.ComputeUnitCameOnline(new { Guid = MyGuid,
                HeartBeat = DateTime.UtcNow.ToEpochMilliseconds() });           
     }
     public void SubscribeToHeartBeats(Guid MyGuid)
     {
         Groups.Add(Context.ConnectionId, MyGuid.ToString());
     }
}

我的客户是 Javascript 客户,它们有方法(如果您也需要查看代码,请告诉我)。但基本上他们会监听ComputeUnitCameOnline并在其运行时调用服务器SubscribeToHeartBeats。这意味着每当服务器计算单元在做一些工作时,它都会调用 Running,这将触发一个ComputeUnitHeartBeaton javascript 客户端。

我希望您可以使用它来了解如何使用 Groups 和 Connections。最后,它还通过添加几行代码来扩展多天蓝色角色:

    GlobalHost.HubPipeline.EnableAutoRejoiningGroups();
    GlobalHost.DependencyResolver.UseServiceBus(
        serviceBusConnectionString,
        2,
        3,
        GetRoleInstanceNumber(),
          topicPathPrefix /* the prefix applied to the name of each topic used */
        );

您可以在 Azure 上的服务总线上获取连接字符串,记住 Provider=SharedSecret。但是在添加 nuget 打包时,连接字符串语法也会粘贴到您的 web.config 中。2 是要拆分多少个主题。主题可以包含 1Gb 的数据,因此您可以根据性能增加它。3 是拆分它的节点数。我使用了 3,因为我有 2 个 Azure 实例和我的本地主机。您可以像这样获得 RoleNumber(请注意,我将 localhost 硬编码为 2)。

private static int GetRoleInstanceNumber()
{
    if (!RoleEnvironment.IsAvailable)
        return 2;

    var roleInstanceId = RoleEnvironment.CurrentRoleInstance.Id;
    var li1 = roleInstanceId.LastIndexOf(".");
    var li2 = roleInstanceId.LastIndexOf("_");
    var roleInstanceNo = roleInstanceId.Substring(Math.Max(li1, li2) + 1);
    return Int32.Parse(roleInstanceNo);
}

您可以在以下位置看到所有内容:http: //taskqueue.cloudapp.net/#/compute-units

于 2012-11-11T05:25:32.507 回答
2

使用 SignalR 时,在客户端连接到服务器后,他们会收到一个连接 ID(这对于提供实时通信至关重要)。是的,它存储在内存中,但 SignalR 也可以在多节点环境中使用。例如,您可以使用 Redis 甚至 Sql Server 背板(更多内容)。长话短说,我们通过背板/服务总线为您处理横向扩展方案,您无需担心。

于 2012-11-10T18:40:55.907 回答