【问题标题】:SignalR dotnet 3.1 webapi hosted on IIS 8 (WebSocket enabled) works few minutes onlySignalR dotnet 3.1 webapi 托管在 IIS 8(启用 WebSocket)上仅工作几分钟
【发布时间】:2021-05-26 09:25:52
【问题描述】:

我在 IIS 8 上托管一个带有 SignalR 的 dotnet 3.1 WebApi,并在服务器上启用了 WebSocket 协议。托管的 API 应用程序在最初的几分钟内运行良好,但一段时间后停止运行,并且不响应任何请求。

客户端在 Angular 11 中,可以正常工作。但发生这种情况时,客户端需要很长时间才能完成 API 请求。

并且必须重新启动应用程序,然后才能再次运行几分钟。

IIS 日志显示此错误

System.InvalidOperationException: The 'InvokeCoreAsync' method cannot be called if the connection is not active

搜索了这个错误,但到目前为止没有任何工作。

控制器结构
/**
   Controller Constructure
**/
        private IDataTracker _iDataTracker;
        private HubConnection _signalRHubConnection;

        public DataTrackingController(IDataTracker iDataTracker){
            _iDataTracker = iDataTracker;
            if(_signalRHubConnection == null || _signalRHubConnection.State == HubConnectionState.Disconnected)
            {
                _signalRHubConnection = new HubConnectionBuilder()
                .WithUrl("http://locally-hosted-url/DataApi/dataHub")
                .WithAutomaticReconnect()
                .Build();
                _signalRHubConnection.StartAsync();
            }
        }
控制器动作
/**
  Controller Action
**/

[HttpPost]
public async Task<IActionResult> TrackDataAsync(DataModel dataObject){
      
      //database call
      var resultData = _iDataTracker.TrackData(dataObject);

      //SignalR Client call
      await _signalRHubConnection.InvokeAsync("SendData", dataObject);

      return Ok(resultData);
}
SignalR 集线器

/**
  Hub class
**/

public class DataHub: Hub
    {
        public void SendData(DataModel dataObject)
        {
            Console.WriteLine("SignalR data: "+ dataObject.IQty);
            Clients.All.SendAsync("ReceiveData",dataObject);
        }

    }

【问题讨论】:

  • Websocket 实际上是基于 TCP 的 HTML。普通 HTTP 为每个请求/响应建立一个新连接。 Websocket 打开连接并保持打开状态,以便您可以在同一连接上发送多个请求/响应。您的连接由于某种原因正在关闭。不知道为什么。您可以从 cmd.exe >Netstat -a 使用。 Netsta 会为您提供所有连接的状态,有时如果出现错误,连接关闭后会显示错误。使用像wireshark或fiddler这样的嗅探器,你可以找出关闭的原因。当关闭开始时,嗅探器将在 TCP 上显示 [FIN]。
  • 有些服务器会关闭一段时间后空闲的连接。在这些情况下,您可能需要实现一个 Keep-Alive,它是一个空消息,用于保持连接处于活动状态。发生异常时,您也可能正在关闭连接。
  • @jdweng 应用程序池启动模式处于 AlwaysRunning 模式,因为被系统进程停止的问题。
  • 不能有两个 TCP 连接具有相同的三个参数 1) 源 IP 2) 目标 IP 3) 端口号。
  • 为什么要从控制器创建/打开集线器?控制器实例的寿命不长,因此可以快速处置集线器。找到任何官方的 SignalR 示例,您就可以看到正确的方法。

标签: c# .net-core signalr iis-8 asp.net-core-signalr


【解决方案1】:

感谢@lex-li 提及控制器实例的问题。所以现在 Hub 是用 IHubContext 实例化的,这显然解决了这里的问题。

/**
   Controller Constructure
**/
        private IDataTracker _iDataTracker;
        private readonly IHubContext<ProductionCountHub> _hubContext;

        public DataTrackingController(IDataTracker iDataTracker,  
                                IHubContext<ProductionCountHub> hubContext){
            _iDataTracker = iDataTracker;
            _hubContext = hubContext;
        }
/**
  Controller Action
**/

[HttpPost]
public async Task<IActionResult> TrackDataAsync(DataModel dataObject){
      
      //database call
      var resultData = _iDataTracker.TrackData(dataObject);

      //SignalR Client call
      await _hubContext.Clients.All.SendAsync("SendData", dataObject);

      return Ok(resultData);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-24
    • 2019-12-29
    • 1970-01-01
    • 2015-05-05
    • 1970-01-01
    相关资源
    最近更新 更多