【问题标题】:Signalr calling specific client from outside the hubSignalr 从集线器外部调用特定客户端
【发布时间】:2012-09-06 07:39:03
【问题描述】:

我知道Chris Fulstow project log4net.signalr,如果您想要一个非生产日志,这是一个好主意,因为它会记录来自所有请求的所有消息。我希望有一些东西可以通过发起它们的请求来区分日志消息并返回到正确的浏览器。

这是我在 appender 中所做的:

 public class SignalRHubAppender:AppenderSkeleton
    {
        protected override void Append(log4net.Core.LoggingEvent loggingEvent)
        {
            if (HttpContext.Current != null)
            {
                var cookie = HttpContext.Current.Request.Cookies["log-id"];
                if (null != cookie)
                {
                    var formattedEvent = RenderLoggingEvent(loggingEvent);
                    var context = GlobalHost.ConnectionManager.GetHubContext<Log4NetHub>();
                    context.Clients[cookie.Value].onLog(new { Message = formattedEvent, Event = loggingEvent });
                }
            }
        }
    }

我正在尝试将会话 ID 附加到 cookie,但这在同一台机器上不起作用,因为 cookie 已被覆盖。 这是我在客户端用来附加事件的代码:

//start hubs
    $.connection.hub.start()
    .done(function () {
        console.log("hub subsystem running...");
        console.log("hub connection id=" + $.connection.hub.id);
        $.cookie("log-id", $.connection.hub.id);
        log4netHub.listen();
    });

因此,只有最后一个连接的页面会显示日志消息。我想知道是否有一些策略可以从发起当前请求的浏览器中获取当前连接 ID(如果有的话)。 我也很想知道是否有更好的设计来实现每个浏览器的日志记录。

编辑

我可以制作一个基于约定名称的 cookie(例如 log-id-someguid ),但我想知道是否有更聪明的方法。

赏金 我决定在这个问题上开始悬赏,我还会询问架构,以查看我的策略是否有意义。 我的疑问是,我在从服务器到客户端的单一“方向”上使用集线器,我用它来记录不是源自对集线器的调用而是源自其他请求(可能是在其他集线器上提出的请求)的活动,是这是一个正确的方法,目标是浏览器可见的 log4net 附加程序?

【问题讨论】:

  • 我从来不需要解决这样的问题,我想到的唯一方法是重写一些 url,以便通过 url 或组合唯一标识每个浏览器/选项卡实例url和cookies
  • @Wasp 问题应用程序是一个 SPA :) 我编辑问题以提出一个额外的想法,看看它是否有意义
  • 我猜对了 :) 但我仍然认为你可以想出一些智能路由规则,在 url 中生成一种唯一的 id 并以某种方式处理。愚蠢的想法,用户转到foo.com,然后您在第一次连接时将他重定向到foo.com/n2998fhn239,并将其保留在您的SPA中
  • @Wasp 好主意,我有点担心 wole 架构不正确。但是关于同一主题的其他示例不区分客户端会话。
  • 我认为这是唯一适用于任何(非侏罗纪)浏览器的解决方案。结合一些生成的 cookie 和 url,您应该能够防止劫持,然后 SignalR 完成剩下的工作。我找不到极端案例,但也许只有我一个人 :)

标签: asp.net-mvc signalr signalr-hub


【解决方案1】:

关于如何正确定位正确的浏览器实例/选项卡(即使在同一个 SPA 上打开多个选项卡)的想法是通过 URL 来区分它们。一种可能的实现方法是在第一次访问时将它们从http://foo.com 重定向到http://foo.com/hhd83hd8hd8dh3,每次随机生成。 url 重写也可以通过其他方式完成,但这只是说明问题的一种方式。这样,appender 将能够检查原始 Url,并通过您保留服务器端的一些映射从 Url 识别正确的 SignalR ConnectionId。实现细节可能会有所不同,但基本思想就是这个。跟踪自第一次连接以来 HttpContext 中可用的更多信息,您还可以实施其他策略以防止任何劫持。

关于你的架构,我可以告诉你,这正是我在ElmahR 中使用它的方式。我有来自通知中心外部的消息(从其他网络应用程序发布的错误),我向连接到该中心的所有客户端(并订阅某些组)进行广播:它工作正常。

我不是权威来源,但我也猜想这样的架构是可以的,即使有多个集线器,因为集线器在一天结束时只是对(一个)持久连接的抽象,它允许您按上下文分组消息传递。在幕后(我正在简化)你只是与来回消息的持久连接,所以无论你在它上面定义什么集线器结构(它只是为了帮助你组织事情)你仍然坚持这种连接,所以你不能做任何伤害。

SignalR 擅长做两件事:大规模广播(客户端)和一对一通信(呼叫者)。只要你不尝试做一些奇怪的事情,比如建立对特定调用者的服务器端引用,你应该没问题,不管有多少集线器,以及它们之间的交互,你都有。

这些是我的结论,来自现场。也许您可以就这个问题向@dfowler 推特,看看他是否有(更多)更权威的指导方针。

【讨论】:

  • 我很高兴听到整体架构有意义,但仍在寻找比 cookie 更好的东西来将消息引导到正确的来源
猜你喜欢
  • 2014-02-10
  • 2011-12-13
  • 1970-01-01
  • 1970-01-01
  • 2013-12-31
  • 1970-01-01
  • 2013-10-29
  • 2023-03-19
  • 2013-03-23
相关资源
最近更新 更多