【问题标题】:nservicebus sagas - stuck trying to understand the purpose and benefitnservicebus sagas - 试图理解目的和好处
【发布时间】:2018-04-05 20:03:48
【问题描述】:

我已多次阅读网站上的文档。我一遍又一遍地阅读相同的文章,我无法理解他们试图通过 sagas 实现什么。此外,互联网上几乎没有与该主题相关的资源。

但我完全无法理解定义所谓的 sagas 的目的和好处。我了解处理程序 (IHandleMessages) - 这些是拦截器。但我无法理解 Saga 的用途。文档中的语言假设我应该知道一些特别的东西来掌握这个想法,但我不知道。

有人可以用简单的话向我解释一下,希望用现实生活中的例子来解释我必须或应该定义 Saga 的情况,这样做有什么好处?我已经创建了一个具有多个端点和 Saga 定义的应用程序,如示例中所示,它可以工作(我猜)但我不明白这些 saga 的定义是什么......在许多示例中,他们使用 Saga 类中的 RequestTimeout() 方法。为什么,为什么有人要故意造成超时?我不想在这里放任何代码片段,因为它不相关,我需要了解我为什么要使用“Sagas”,不管它是什么意思?

谢谢。

【问题讨论】:

  • lol++ 我正要在超级用户(StackExchange)上问同样的问题,但感谢#Sean Feldman 的回答

标签: nservicebus nservicebus-sagas


【解决方案1】:

NServiceBus Saga 是企业集成模式book 中描述的Process Manager 的变体。

要了解何时使用 Saga,必须先了解它。假设您仅使用常规消息处理程序来实现新用户注册过程。在某个时间点,您发现只有 40% 的全新注册人确认了他们的电子邮件地址并成为活跃用户帐户。您想解决两件事。

  1. 在注册后 24 小时后通过发送提醒来提醒新注册者确认其电子邮件。
  2. 在 48 小时内从数据存储中删除注册人信息(例如电子邮件)以符合GDPR

现在您如何使用常规消息处理程序来做到这一点?处理程序将通过生成带有确认链接的电子邮件来接收初始请求(第一条消息,m1)以启动注册,仅此而已。一旦处理程序完成,它就永远完成了。但是您的过程还没有完成。这是一个长期运行的逻辑过程,必须跨越 48 小时才能完成。它不再只是单个消息处理,而是此时的工作流。具有多个检查点的工作流程。类似于状态机。要从一种状态转移到另一种状态,必须满足某个条件。在 NServiceBus 的情况下,这些将是消息。任何用户操作都不会触发 24 小时后发送提醒的消息(我们称之为 m2)。这是一个“系统”消息。应自动启动的定时消息。指示系统删除注册人信息的消息也是如此如果验证链接未激活。可以观察到主题:需要在未来安排消息以重新水合工作流并从上次离开的状态继续。

这就是超时。这些是从上次在某个时间点(分钟、小时、天、月、年)离开的点重新补充/继续传奇/工作流程的请求。

这就是这种工作流程在传奇中的样子(过于简单,并没有考虑到所有边缘情况)。

class RegistrationWorkflow : 
  Saga<WorkflowState>,
  IAmStartedByMessages<RegisterUser>,
  IHandleMessages<ActivationReceived>,
  IHandleTimeouts<NoResponseFor24Hours>,
  IHandleTimeouts<NoResponseFor48Hours>
{
  protected override void ConfigureHowToFindSaga(SagaPropertyMapper<WorkflowState> mapper)
  {
    // omitted for simplicity, see message correlation
    // https://docs.particular.net/nservicebus/sagas/message-correlation
  }

  public async Task Handle(RegisterUser message, IMessageHandlerContext context)
  {
    Data.RegistrationId = message.RegistrationEmail;

    await RequestTimeout<NoResponseFor24Hours>(context, TimeSpan.FromHours(24));
  }

  public async Task Handle(ActivationReceived message, IMessageHandlerContext context)
  {
    Data.ConfirmationReceived = true;

    // email was confirmed and account was activated
    await context.Send(new PromoteCandidateToUser 
    { 
      CandidateEmail = Data.RegistrationEmail 
    });

    MarkAsComplete()
  }

  public async Task Timeout(NoResponseFor24Hours timeout, IMessageHandlerContext context)
  {
    if (Data.ConfirmationReceived)
    {
      return;
    }

    await context.Send(new SendReminderEmailToActivateAccount { Email = Data.RegistrationEmail });        

    await RequestTimeout(context, TimeSpan.FromHours(24), new NoResponseFor48Hours());
  }

  public async Task Timeout(NoResponseFor48Hours timeout, IMessageHandlerContext context)
  {
    if (Data.ConfirmationReceived)
    {
      return;
    }

    context.Send(new CleanupRegistrationInformationForGDPRCompliancy 
    { 
      RegistrationEmail = Data.RegistrationEmail 
    });

    MarkAsComplete();
  }
}

由于这是一个状态机,因此状态在 Saga 调用之间保持不变。调用可能由 saga 可以处理的消息(RegisterUserActivationReceived)或到期的超时(NoResponseFor24HoursNoResponseFor48Hours)引起。对于这个特定的 saga,状态由以下 POCO 定义:

class WorkflowState : ContainSagaData
{
  public string RegistrationEmail { get; set; }
  public bool ConfirmationReceived { get; set; }
}

超时只不过是被推迟的普通IMessages。此示例中使用的超时将是

class NoResponseFor24Hours : IMessage {}
class NoResponseFor48Hours : IMessage {}

希望这能阐明Sagas 的概念,Timeouts 是什么以及如何使用它们。我没有进入Message CorrelationSaga Concurrency 和其他一些细节,因为这些细节可以在您提到的文档站点上找到。这将我们带到下一点。

我已多次阅读他们网站上的文档。这绝对是可怕的。我一遍又一遍地阅读相同的文章,我无法理解他们想要达到的目标。

该网站有一个您绝对应该提供的反馈机制。

此外,互联网上几乎没有与此主题相关的资源。

希望看到您发布有关此主题的博客(或一系列帖子)。通过这样做,您将做出积极的贡献。

完全免责声明:我在 NServiceBus 工作

【讨论】:

  • 感谢您的精彩解释,肖恩
  • 随时。请不要犹豫,通过“反馈”按钮在网站上提供反馈。在 Sagas 或您遇到问题的任何其他文档上。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多