查询微服务架构内的异步操作状态
Query asynchronous operation state within a micro service architecture
我们正在重新设计一些 REST API 端点以过渡到微服务架构。
这里我们正在处理端点 /invitations/:id/confirm
。
此端点使用提供的 Invitation
.
创建 User
、Account
我们有 3 个集合 Invitation
、User
和 Account
。
我们目前的标称流量如下:
- 检查
Invitation
是否存在
- 确保邀请可以被确认
- 创建
User
- 创建
Account
- 删除
Invitation
- Return
UserId
此操作是在进程内完成的,这解释了为什么我们可以立即 return 一个 UserId。我们只需从数据库加载我们的聚合,执行相关的业务逻辑并保存结果。
引入微服务会需要异步处理。换句话说,我们应该向总线发送命令和 return 状态码 202.
在我们的计划中,我们想要触发一个名为 RequestInvitationConfirmation
的命令。实例化此命令时将进行基本验证。
然后这个命令将通过总线发送到一个消费者负责:
- 加载邀请聚合(确保它存在)
- 调用 RequestConfirmation 方法(将检查邀请是否可以确认)
- 引发 InvitationConfirmationRequested
事件
InvitationConfirmationRequested
事件将触发负责编排跨服务通信的 SAGA
OnInvitationConfirmationRequested
- 发送
CreateUser
命令
OnUserCreated
- 发送
CreateAccount
命令
OnAccountCreated
- 发送
DeleteInvitation
命令
OnInvitationDeleted
- 提高
InvitationConfirmed
由于它是异步的,我们需要提供一种获取当前操作状态的方法。我看到 (https://www.adayinthelifeof.nl/2011/06/02/asynchronous-operations-in-rest/, https://asyncrestapi.docs.apiary.io/#) 这是一种常见的方法
是提供 /queue/:id
或 /actions/:id
端点。
这就是我们感到困惑的地方。当 SAGA 与另一个 SAGA 的状态可能完全不同时,您如何提供单一端点?
感谢
为了让您的 saga 在单个流的范围内处理消息,您必须将所有消息与正确的实例相关联。当一个saga被第一条消息启动时,saga identity根据规则生成:
Event(() => ItemAdded, x => x.CorrelateBy(cart => cart.UserName, context => context.Message.UserName)
.SelectId(context => Guid.NewGuid()));
所以这个 id 将用作持久保存到 saga 存储库的 saga 的标识。
class ShoppingCart :
SagaStateMachineInstance
{
public Guid CorrelationId { get; set; }
public string CurrentState { get; set; }
这里的CorrelationId
是saga id,因此是整个流程的相关id。
如果您有权访问您的 saga 存储库(并且您已经这样做),则可以很容易地公开 HTTP API 端点以通过查看 CurrentState
属性 在你用来保存 sagas 的数据库中的 saga 状态。
我们正在重新设计一些 REST API 端点以过渡到微服务架构。
这里我们正在处理端点 /invitations/:id/confirm
。
此端点使用提供的 Invitation
.
User
、Account
我们有 3 个集合 Invitation
、User
和 Account
。
我们目前的标称流量如下:
- 检查
Invitation
是否存在 - 确保邀请可以被确认
- 创建
User
- 创建
Account
- 删除
Invitation
- Return
UserId
此操作是在进程内完成的,这解释了为什么我们可以立即 return 一个 UserId。我们只需从数据库加载我们的聚合,执行相关的业务逻辑并保存结果。
引入微服务会需要异步处理。换句话说,我们应该向总线发送命令和 return 状态码 202.
在我们的计划中,我们想要触发一个名为 RequestInvitationConfirmation
的命令。实例化此命令时将进行基本验证。
然后这个命令将通过总线发送到一个消费者负责:
- 加载邀请聚合(确保它存在)
- 调用 RequestConfirmation 方法(将检查邀请是否可以确认)
- 引发 InvitationConfirmationRequested
事件
InvitationConfirmationRequested
事件将触发负责编排跨服务通信的 SAGA
OnInvitationConfirmationRequested
- 发送
CreateUser
命令
- 发送
OnUserCreated
- 发送
CreateAccount
命令
- 发送
OnAccountCreated
- 发送
DeleteInvitation
命令
- 发送
OnInvitationDeleted
- 提高
InvitationConfirmed
- 提高
由于它是异步的,我们需要提供一种获取当前操作状态的方法。我看到 (https://www.adayinthelifeof.nl/2011/06/02/asynchronous-operations-in-rest/, https://asyncrestapi.docs.apiary.io/#) 这是一种常见的方法
是提供 /queue/:id
或 /actions/:id
端点。
这就是我们感到困惑的地方。当 SAGA 与另一个 SAGA 的状态可能完全不同时,您如何提供单一端点?
感谢
为了让您的 saga 在单个流的范围内处理消息,您必须将所有消息与正确的实例相关联。当一个saga被第一条消息启动时,saga identity根据规则生成:
Event(() => ItemAdded, x => x.CorrelateBy(cart => cart.UserName, context => context.Message.UserName)
.SelectId(context => Guid.NewGuid()));
所以这个 id 将用作持久保存到 saga 存储库的 saga 的标识。
class ShoppingCart :
SagaStateMachineInstance
{
public Guid CorrelationId { get; set; }
public string CurrentState { get; set; }
这里的CorrelationId
是saga id,因此是整个流程的相关id。
如果您有权访问您的 saga 存储库(并且您已经这样做),则可以很容易地公开 HTTP API 端点以通过查看 CurrentState
属性 在你用来保存 sagas 的数据库中的 saga 状态。