部署到测试服务器时具有请求/响应超时的MassTransit传奇

时间:2018-08-02 08:00:08

标签: c# asp.net-core masstransit

我有一个完全正常运行的MassTransit传奇,它运行一些命令,然后执行请求/响应调用以查询数据库,然后最终将响应返回给调用控制器。

在本地,所有这些现在都可以在99%的时间内正常运行(由于我在这里获得了很多支持)。但是,当部署到具有RabbitMQ的本地副本和运行2个ASP.NET Core服务的Azure VM时,对saga的第一次调用会立即通过,但随后的所有调用都会超时。

我觉得这可能与我使用InMemorySagaRepository这一事实有关(从理论上讲,这对于我的用例来说应该没问题)。

传奇的初始配置如下:

InstanceState(s => s.CurrentState);

Event(() => RequestLinkEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => LinkCreatedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => CreateLinkGroupFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => CreateLinkFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));
Event(() => RequestLinkFailedEvent, x => x.CorrelateById(context => context.Message.LinkId));

Request(() => LinkRequest, x => x.UrlRequestId, cfg =>
{
            cfg.ServiceAddress = new Uri($"{hostAddress}/{nameof(SelectUrlByPublicId)}");
            cfg.SchedulingServiceAddress = new Uri($"{hostAddress}/{nameof(SelectUrlByPublicId)}");
            cfg.Timeout = TimeSpan.FromSeconds(30);
});

值得注意的是,我的LinkId始终是唯一的Guid,因为它是在发送消息之前在控制器中创建的。

另外,当我重新启动apppool时,它在第一次调用时再次起作用,然后再次开始超时。

我觉得某些地方可能锁定了某个东西,但是我无法在本地复制它!

1 个答案:

答案 0 :(得分:0)

所以我想在这里发表自己的解决方案,希望将来能对其他人有所帮助。

我进行了3个根本性的更改,无论是单独还是组合都解决了此问题,无论我使用InMemorySagaRepository,Redis还是MongoDB,一切都可以100%地运行并且有效。

问题1

如我在此处发布的另一个问题中所述:

MassTransit saga with Redis persistence gives Method Accpet does not have an implementation exception

在我的SagaStateMachineInstance类中,当它应该是这样的字符串时,我错误地将CurrentState属性声明为“州”类型:

public string CurrentState { get; set;}

这是一个基本问题,当我开始尝试添加持久性时它就暴露出来了,因此在使用InMemorySagaRepository时也可能引起麻烦。

问题2

事后看来,我怀疑这可能是我的主要问题,我并不完全相信我已经以最佳方式解决了问题,但我对情况感到满意。

我确保最终状态在所有州都得到管理。我认为正在发生的事情是我的请求/响应在更新传奇的CurrentState之前已经完成。我通过尝试使用MongoDB作为我的持久性并看到我的sagas尚未完全处于倒数第二状态而陷入困境。

问题3

这应该是不必要的,但是我想将其添加为那些有问题的人可以考虑/尝试的东西。

我从传奇中删除了请求/响应步骤,并用发布/订阅替换了它。为此,我向消费者发布了一个事件,该事件在完成时会发布带有CorrelationId的事件(如我的另一期中@ alexey-zimarev所建议)。因此,在执行查询(即reuqest)的使用者中,我会在查询完成后执行以下操作:

context.Publish(new LinkCreatedEvent { ... , CorrelationId = context.Message.CorrelationId })

因为CorrelationId位于其中,所以我的传奇故事将其拾取并按如下方式处理事件:

When(LinkCreatedEvent )
   .ThenAsync(HandleLinkCreatedEventAsync)
   .TransitionTo(LinkCreated)

我对现在的一切工作感到非常满意,并对将解决方案付诸实践充满信心。