【问题标题】:SignalR hub hangs on IISSignalR 集线器在 IIS 上挂起
【发布时间】:2016-11-24 17:36:28
【问题描述】:

我们在 ASP.NET Web 应用程序中使用 SignalR 库。代码如下:

服务器:

[HubName("ticketsCounterHub")]
public class MassivePrintHub : Hub
{
    public void PostTicketsCount(long count)
    {
        Clients.All.Send(count);
    }
}

public class HubFactory
{
    private HubFactory() {}

    public static readonly HubFactory Current = new HubFactory();

    public IHubProxy GetMassivePrintHubProxy()
    {
        var hubConnection = new HubConnection(ConfigUtils.GetRequiredSettingValue("adminPath"));
        var hubProxy = hubConnection.CreateHubProxy("ticketsCounterHub");
        hubConnection.Start().Wait();
        return hubProxy;
    }
}

客户端(JavaScript):

MassivePrintApp.controller("ListController", function ($scope, Dates) {
    var hubManager = (function () {
        var massivePrintHub = $.connection.ticketsCounterHub;
        $.connection.hub.start();
        return { massivePrintHub: massivePrintHub };
    } ());

    hubManager.massivePrintHub.client.Send = function (ticketsCount) {
        $scope.action.Quantity = ticketsCount;
        $scope.$digest();
    };
});

代码的关键部分在MVC控制器中:

public FileResult PrintAction(int actionId, int count, DateTime actionDate, bool isThermo=false)
{
    var ticketsCount = _ticketService.GetTicketsInStatusCount(actionId, actionDate, TicketStatusEnum.ToPrint);

    HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);

    var stream = new MemoryStream();
    xmlResponse.Save(stream);
    stream.Flush();
    stream.Position = 0;
    return File(stream,ContentTypeEnum.XML.ToString(),String.Format("массовая {0} мероприятия {1} {2}шт.xml", isThermo?"термопечать":"печать", action.Artist,count));
}

如你所见,我们有这一行:

HubFactory.Current.GetMassivePrintHubProxy().Invoke("PostTicketsCount", ticketsCount);

这会导致问题,即每当我们调用它时,就会在 IIS 的“请求”部分添加一个集线器实例。

我知道我们已经在 J​​avaScript 代码中启动了集线器,但我不确定如何使用现有连接或如何摆脱 HubFactory 或删除创建的集线器实例。

而且我不明白为什么集线器会挂在 IIS 上。

【问题讨论】:

  • Hub 类是否与 MVC 控制器位于不同的应用程序中?如果不是,那么您可以通过 hub 上下文调用,而不是创建 hubproxy,如下所示:asp.net/signalr/overview/guide-to-the-api/…
  • MVC 控制器放置在主 ASP.NET 应用程序使用的依赖项目中。我已经尝试过以这种方式使用集线器上下文: IHubContext context = GlobalHost.ConnectionManager.GetHubContext(); context.Clients.All.Send(ticketsCount);但是,它不起作用。也许我做错了什么。
  • Hub 也被放置在另一个项目中。
  • 你不是在这里陷入僵局吗:hubConnection.Start().Wait();
  • 应该写什么?如果你写: hubConnection.Start();有错误信息:{"ErrorMessage":"连接尚未建立。","ErrorCode":1001}

标签: asp.net signalr


【解决方案1】:

我想从一个更简单的例子开始会对你有很大帮助。之后,您可以考虑以不同方式托管您的 SignalR 服务器(控制台应用程序或 Windows 服务),基本不会改变

(首次安装 SignalR:NuGet:install-package Microsoft.AspNet.SignalR

我做了一个简单的网络应用示例。该项目有一个 Hub 类:

using Microsoft.AspNet.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace SRTest
{
    public class MassivePrintHub : Hub
    {
        private static IHubContext hubContext = GlobalHost.ConnectionManager.GetHubContext<MassivePrintHub>();

        // Can be called from your Javascript code
        public void PostTicketsCount(long count)
        {
            Clients.All.Send(count);
        }

        // Can be called from your c# code
        public static void Static_PostTicketsCount(long count)
        {
            hubContext.Clients.All.Send(count);
        }
    }
}

一个 Owin 启动类:

using Microsoft.AspNet.SignalR;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(SRTest.Startup))]
namespace SRTest
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var hubConfiguration = new HubConfiguration();
            hubConfiguration.EnableDetailedErrors = true;
            app.MapSignalR(hubConfiguration);
        }
    }
}

页面(Razor 只是为了能够调用一个模拟器,该模拟器调用一个 c# 类从后端发布消息):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>TEST PAGE</title>

    <!--Reference the jQuery library. -->
    <script src='Scripts/jquery-1.6.4.js'></script>
    <!--Reference the SignalR library. -->
    <script src='Scripts/jquery.signalR-2.2.0.js'></script>
    <!--Reference the autogenerated SignalR hub script. -->
    <script src="signalr/hubs"></script>

</head>
<body>

    THIS IS A TEST PAGE
    <!-- Call simulator (trigger event every 5 seconds) -->
    @{SRTest.SendFromBackEnd.SimulateSend();}

<script>
    $(function () {
        var printHub = $.connection.massivePrintHub;

        // when send event happens
        printHub.client.send = function (count) {
            console.log("Send " + count + " tickets");
        };

        $.connection.hub.start().done(function () {
            console.log("Connected");
        });

        $.connection.hub.logging = true;
    });
</script>

</body>
</html>

我添加了一个虚拟类,它每 5 秒通过 hubcontext 触发事件。

using System.Threading;
using System.Web;

namespace SRTest
{
    public class SendFromBackEnd
    {
        public static void SimulateSend()
        {
            new Thread(() =>
            {
                Thread.CurrentThread.IsBackground = true;
                while (true)
                {
                    MassivePrintHub.Static_PostTicketsCount(2);
                    Thread.Sleep(5000);
                }
            }).Start();

        }
    }
}

我在 SignalR 中添加了一些日志记录,添加了一些调试点,它将帮助您了解基础知识,然后构建您计划构建的内容会容易得多。

编辑

关于挂起请求:只要您有一个使用 SSE 或 AJAX 长轮询连接到 SignalR 服务器的客户端,您就会有一个持续的请求,该请求永远不会完成。 (在 AJAX 长轮询的情况下,它会在很短的时间内完成并返回)。在我只使用 Javascript 客户端的应用程序中,我只会在我正在监听事件的页面打开时看到请求。如果没有打开页面或静态页面,则没有请求。 在我使用 .NET 客户端的应用程序中,只要两个应用程序都在运行,并且两个 Sartup 类都执行,即使没有打开页面,请求也将始终存在。 (因为 .NET 客户端仍在监听事件。)

欲了解更多信息:http://hanselminutes.com/291/damian-edwards-explains-the-realtime-web-for-aspnet-with-signalr

【讨论】:

  • 我已在我的 MVC 控制器中注释掉 Invoke 调用,并尝试使用您的静态调用,但它不起作用,并且 IIS 上仍然挂起 SIgnalR 请求。使用 Invoke 一切正常,但 SIgnalR 请求仍然挂在 IIS 上。我的目标是摆脱挂起的请求。为什么挂了?
  • 什么是客户端协议?
  • 实际上,MVC 控制器方法的调用是从主 ASP.NET 应用程序以这种方式完成的: 获取文件 MVC控制器放置在单独的DLL中。我不确定这是否会影响问题。
  • 如果在JS中启用$.connection.hub.logging = true;会看到协商步骤。
  • 或者查看请求时会看到yourApp/signalr/...clientProtocol=1.4&amp;transport=serverSentEvents...
【解决方案2】:

这是一个线程相关的问题。试试这样

Task.Run(() => connection.Start().ContinueWith(task =>
            {

                 .....

            })).Wait();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-09
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多