c# - 带有 Redis 横向扩展/背板的 ASP.NET SignalR 导致服务器负载线性增加
问题描述
我在两个不同的 Windows 服务器上运行 ASP.NET Web 应用程序 (.NET Framework 4.7.1)。每个应用程序实例都有一个 SignalR 消息服务器,其中包含用于不同类型消息的九个不同集线器。当两台服务器都在线时,会使用 Redis 背板进行 SignalR 横向扩展。
使用
- .NET 框架 4.7.1
- ASP.NET SignalR 2.4.2 版(JS 和 .NET 客户端也使用此版本)
StackExchange.Redis
版本 2.2.62(以前使用StackExchange.Redis.StrongName
1.2.6)- Redis 服务器 3.2.12 - 禁用集群支持
任何一台服务器单独运行时都没有问题(无背板);但是,当两台服务器一起运行时,Redis 中的数据量不断增加,每台服务器使用的内存量不断增长,直到某些应用程序停止工作或客户端接收消息出现明显延迟。这可能需要一天到一周的时间。
设置
两个服务器在一个代理后面活动
每台服务器每天在不同时间回收一次应用程序池
在任何给定时间都有数百个 SignalR JS 和 SignalR.NET 客户端,每个客户端都连接到一个或多个集线器
不使用粘性会话(对于 .NET Core 是必需的,但对于 ASP 则不需要)
仅使用 Web 套接字协议
Redis 中的不同通道用于服务器之间的其他消息,例如客户端连接或断开连接时
所有消息都从服务器发送到客户端,单向
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(110); GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(30); GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(10); GlobalHost.Configuration.DefaultMessageBufferSize = 32; // This is the minimum size GlobalHost.DependencyResolver.UseStackExchangeRedis(new RedisScaleoutConfiguration(RedisHostName, RedisAppNameKey)); var hubConfiguration = new HubConfiguration { EnableDetailedErrors = true }; app.MapSignalR(hubConfiguration);
日志中没有异常或错误,我无法在另一个环境中重现该问题,包括使用大量客户端和消息进行负载测试。
查看 SignalR Redis 消息,我注意到有些消息被重复多次。查看代理日志,我注意到即使在一台服务器运行的情况下也有连续的 SignalRabort
和消息。negotiate
当记录客户端连接和断开连接时,有时对于ConnectionId
相同的集线器会有重复的连接。
Redis 的网络配置文件。Falls 是应用程序池回收的时候。
服务器开始出现问题之前的内存。SignalR 占据了大部分。
编辑 1:我对两台服务器进行了大约一个小时的 SignalR 跟踪。
bus.log.txt
在应用程序池被回收之前是干净的,没有例外。
transports.log.txt
在两台服务器上的日志中都有多个异常。
SignalR.Transports.WebSocketTransport Error: 0 : OnError(7824eb1d-5916-4295-afe2-632fc8c01130, System.Net.WebSockets.WebSocketException (0x80070026): Reached the end of the file
SignalR.Transports.WebSocketTransport Error: 0 : OnError(d8f299ca-d658-40e8-af83-ba4bbc0166f2, System.Net.WebSockets.WebSocketException (0x800703E3): The I/O operation has been aborted because of either a thread exit or an application request
更新: 根据 SignalR 开发团队的说法,异常是正常的,不是我的问题的原因。
解决方案
推荐阅读
- logging - 用于高效日志文件压缩的库
- watchkit - 在 watchOS 的后台发出网络请求
- gtk3 - Yocto 配置:错误:未满足软件包要求(gtk+-3.0 >= 3.14.0)
- oracle - 如何将 PL/SQL 脚本的结果输出到网格?
- javascript - 返回 JSON 格式的 HTML 并调用函数
- php - MySQL: Acquiring data from related tables
- regex - 正则表达式解析问题
- awk - awk 从具有不同 RS 的文件中查找值
- ruby-on-rails - Ruby-on-Rails 显示问题 - 2018 年 5 月仅存在一次,但我的应用程序显示了 7 次
- android - RecyclerView 中的第一项不可点击