Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/32.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在信号器中通过用户ID查找连接_C#_Asp.net_Signalr - Fatal编程技术网

C# 在信号器中通过用户ID查找连接

C# 在信号器中通过用户ID查找连接,c#,asp.net,signalr,C#,Asp.net,Signalr,我有一个网页,它使用ajax轮询从服务器获取股市更新。我想改用信号器,但我很难理解它是如何工作的 好吧,这不是真正的股市更新,但类比是有效的 我看到的信号器示例向当前连接、所有连接或组发送消息。在我的示例中,股票更新发生在当前连接之外,因此没有“当前连接”这样的东西。而且一个用户的帐户与一些股票关联,因此向所有连接或组发送股票通知也不起作用我需要能够找到与特定用户ID关联的连接。 下面是一个伪代码示例: foreach(var stock in StockService.GetStocksWit

我有一个网页,它使用ajax轮询从服务器获取股市更新。我想改用信号器,但我很难理解它是如何工作的

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

我看到的信号器示例向当前连接、所有连接或组发送消息。在我的示例中,股票更新发生在当前连接之外,因此没有“当前连接”这样的东西。而且一个用户的帐户与一些股票关联,因此向所有连接或组发送股票通知也不起作用我需要能够找到与特定用户ID关联的连接。

下面是一个伪代码示例:

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)这不利于多节点网站。这两点对于我们当前的应用至关重要。这让我觉得我必须向所有节点发送一条消息,以找到连接到每个节点的用户>>我的大脑在混乱中爆炸

问题


如何为特定用户找到可扩展的连接?我是否有错误的想法?

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

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

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

await HubProxy.Invoke("ComputeUnitReqisted", _ComputeGuid);
每一次他们做一些他们称之为

HubProxy.Invoke("Running", _ComputeGuid);
其中,代理是:

HubConnection Hub = new HubConnection(RoleEnvironment.IsAvailable ?
                    RoleEnvironment.GetConfigurationSettingValue("SignalREndPoint"):
                    "http://taskqueue.cloudapp.net/");
IHubProxy HubProxy = Hub.CreateHubProxy("ComputeUnits"); 
我使用了RoleEnviroment.IsAvailable,因为我现在可以将其作为Azure角色、控制台应用程序或.NET 4.5中的任何应用程序运行。该中心位于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客户机,它们有用于的方法(如果您还需要查看此方法的代码,请告诉我)。但是基本上,它们是为
计算机联机
而列出的,当运行时,它们调用服务器
SubscribeToHeartBeats
。这意味着,每当服务器计算单元执行某些工作时,它都会调用Running,这将在javascript客户端上触发
ComputeUnitHeartBeat

我希望您可以使用这个来了解如何使用组和连接。最后,它还通过添加几行代码来扩展azure角色:

    GlobalHost.HubPipeline.EnableAutoRejoiningGroups();
    GlobalHost.DependencyResolver.UseServiceBus(
        serviceBusConnectionString,
        2,
        3,
        GetRoleInstanceNumber(),
          topicPathPrefix /* the prefix applied to the name of each topic used */
        );
您可以在azure上的servicebus上获取连接字符串,记住Provider=SharedSecret。但是在添加nuget打包时,connectionstring语法也会粘贴到web.config中。 2是要拆分多少个主题。主题可以包含1Gb的数据,因此可以根据性能增加它。 3是要将其拆分的节点数。我使用3是因为我有2个Azure实例和我的localhost。您可以这样获得RoleNumber(注意,我将localhost硬编码为2)


您可以在以下位置现场观看:

谢谢泰勒-这清楚地表明信号员应该工作。关于如何做到这一点有什么建议吗?我还不太清楚如何将SqlServer与Signal一起使用,或者如何找到连接。我提供了一个我昨晚所做的示例,这都是Taylor所说的,只是详细解释了。我们已经简化了很多,并且很快将发布一个nuget包。谢谢你这篇伟大的文章!我发现它很简单,不知道什么会变得更简单:)
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);
}