在IIS下加载.net framework时的大规模传输超时



在生产中加载时,我们收到"RabbitMQ.Client.Exceptions.ConnectFailureException"连接失败"MassTransit.RequestTimeoutException"等待响应超时。消费者接收消息并将其发送回去。这就像web应用程序没有监听,或者无法接受连接。

我们正在运行ASP。.NET web应用程序(不是MVC)在IIS上的Windows Server 2019上的。NET Framework 4.6.2上。我们正在使用MassTransit 7.0.4。在生产环境中,在负载下,我们可能会在处理RabbitMQ上的套接字或传输超时时遇到一些异常。很难在Dev中复制它们。RabbitMQ在镜像中,一旦我们打开高负载服务,从140条消息/秒上升到250条消息/秒,似乎就会发生这种情况。

我有一些关于代码架构的问题,然后如果其他人遇到这种超时问题。

问题:

  1. 我应该有静态范围的IBusControl吗?也就是说,它应该是静态的内部全局asax?如果它下面是单例,那又有什么关系呢?
  2. 我应该创建一个新的IBusControl并启动它每个请求(也许把它粘在applicationbeginrequest)。那会有什么不同吗?
  3. 如果这是一个资源问题(耗尽线程,连接或某些资源),添加另一个工作进程会影响我能够打开的连接总数吗?

例外:

MassTransit.RequestTimeoutException
Timeout Waiting for response
Stacktrace:
System.Runtime.ExceptionServices.ExceptionDispathInfo.Throw
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
MassTransit.Clients.ResponseHandlerConnectionHandle`1+<GetTask>d_11.MoveNext
System.Threading.ExecutionContext.RunInternal

RabbitMQ.Client.Exceptions.ConnectFailureException
Connection failed
Statcktrace:
RabbitMQ.Client.Impl.SocketFrameHandler.ConnectOrFail
RabbitMQ.Client.Impl.SocketFrameHandler.ConnectUsingAddressFamily
RabbitMQ.Client.Impl.SocketFrameHandler..ctor
RabbitMQ.Client.ConnectionFactory.CreateFrameHandler
RabbitMQ.Client.EndPointResolverExtensions.SelectOne
RabbitMQ.Client.ConnectionFactory.CreateConnection

我们的代码如何工作(概述)

静态IBusControl,在某人第一次尝试生成消息时实例化。整个连接和发送代码在这里有点大(连接工厂和其他度量类,但下面是有趣的部分)。

Static IBusControl B;

B = Bus.Factory.CreateUsingRabbitMq(x =>
{
hostAddress = host.HostAddress;
x.Host(new Uri(host.HostAddress), h =>
{
h.Username(host.UserName);
h.Password(host.Password);
});
x.Durable = false;
x.SetQueueArgument("x-message-ttl", 600000);
});
B.Start(new TimeSpan(0, 0, 10));

// Then send the Actual Messages
// Generic with TRequest and TResponse : class BaseMessage
// Pulling the code out of a few different classes

string serviceAddressString = string.Format("{0}/{1}?durable={2}", HostAddress, ChkMassTransit.QueueName(typeof(TRequest), typeof(TResponse)), false ? "true" : "false");
Uri serviceAddress = new Uri(serviceAddressString);
RequestTimeout rt = RequestTimeout.After(0, 0, 0, 0, timeout.Value);
IRequestClient<TRequest> reqClient = B.CreateRequestClient<TRequest>(serviceAddress, rt);
var v = reqClient.GetResponse<TResponse>(request, sendInfo.CT, sendInfo.RT);
if ( v.Wait(timeoutMS) ) { /*do some stuff*/ }

首先,我发现你缺少async令人不安。在基于tpl的代码中使用Wait或类似的东西是导致死亡和破坏,痛苦和折磨,狗和猫生活在一起等的配方。

  1. 是的,您应该有一个在应用程序启动时启动的总线实例。由于您正在做请求/响应,请在总线配置器上设置AutoStart = true,以确保它已全部预热并准备就绪。

  2. 绝不,不,只有一个总线!

  3. 每个总线实例只有一个连接,所以你不应该在RabbitMQ上看到任何与容量相关的资源问题。

MassTransit 7.0.4真的很老了,你可以考虑简单的升级7.3.1,看看它是否对你有所改善。这是v7代码库可用的最后一个版本。

最新更新