CRQS:排队命令的好处

时间:2015-05-13 15:54:05

标签: php message-queue cqrs

我无法真正理解在CommandBus中排队命令的好处。

这是我非常简单的CommandBus实现:

class CommandBus implements ICommandBus
{
  private $handlerLocator;

  public function __construct(ICommandHandlerLocator $handlerLocator)
  {
      $this->handlerLocator = $handlerLocator;
  }

  public function handle(ICommand $command)
  {
      $handler = $this->handlerLocator->getHandlerInChargeFor($command);

      try{
          $handler->handle($command);
      }
      catch(\Exception $e) {
          throw $e;
      }
  }

}

这个实现实际上是在TransactionnalCommandBus中装饰的,它是一种记录数据库的持久命令,但由于它不是我的问题,我不会在这里显示它

现在让我们关注排队CommandBus:

class QueuingCommandBus implements ICommandBus
{
    private $innerCommandBus;
    private $commandQueue = array();
    private $isHandling = false;

    public function __construct(CommandBus $commandBus)
    {
        $this->innerCommandBus = $commandBus;
    }

    public function handle(ICommand $command)
    {
        $this->commandQueue[] = $command;

        if($this->isHandling)
        {
            return;
        }

        while($command = array_shift($this->commandQueue))
        {
            $this->isHandling = true;
            $this->innerCommandBus->handle($command);
        }

        $this->isHandling = false;
    }
}

除了事实上现在要抛出我的例外情况要困难得多,我真的没有看到消息队列的好处......

有人可以开导我吗?

2 个答案:

答案 0 :(得分:2)

在极少数情况下,您需要以先进/先出的方式串行处理命令,队列是实现此目的的简单方法。除此之外,我认为使用内存中队列处理命令没有任何实际好处。

在SOA场景中,使用排队技术(MSMQ,RabbitMQ等)非常有用,因为它允许持久的消息传递并增强系统可靠性。即使接收端点已关闭,该命令仍可排队等待,并在系统重新联机时准备就绪。

您的评论现在更难以抛出异常在这些情况下绝对正确,因为端点现在需要发送确认或错误以让客户端知道命令失败或成功。然而,拥有一个更强大的系统的好处通常超过这个轻微的不便。

答案 1 :(得分:1)

在大多数情况下,您不需要总线来执行命令。如果您因某些原因需要异步命令,我建议您仅使用命令总线。如果你不使用总线,那么处理命令就不那么复杂了。

CQRS没有说您需要使用总线来执行命令或事件。在CQRS中注意到您的命令和事件需要是异步的。

如果使用总线,则需要在发送命令之前验证命令。如果他们失败了,就像你说的那样,将更难以与客户沟通。你可以通过提出一些说明命令失败的事件来做到这一点,但直接向客户端返回一些东西要容易得多。