【问题标题】:CRQS : benefits of queuing commandsCRQS:排队命令的好处
【发布时间】:2015-07-25 00:51:15
【问题描述】:

我无法真正理解在 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;
    }
}

除了现在抛出异常变得更加困难之外,我真的看不到消息队列的好处......

有人可以启发我吗?

【问题讨论】:

    标签: php message-queue cqrs


    【解决方案1】:

    在您需要以先进/先出方式串行处理命令的罕见特定情况下,队列是完成此任务的一种简单方法。除此之外,我认为使用内存队列处理命令并没有真正的好处。

    在 SOA 场景中,使用队列技术(MSMQ、RabbitMQ 等)可能非常有益,因为它允许持久的消息传递并增强系统可靠性。即使接收端点宕机,命令仍然可以排队等待系统恢复在线。

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

    【讨论】:

      【解决方案2】:

      在大多数情况下,您的命令不需要总线。如果您出于某种原因需要异步命令,我建议您仅使用命令总线。如果您不使用总线,那么您的命令处理将不那么复杂。

      CQRS 并没有说明您需要为您的命令或事件使用总线。在 CQRS 中指出,您的命令和事件需要是异步的。

      如果您使用总线,则需要在发送命令之前验证您的命令。如果他们失败了,正如你所说,将其传达给客户会更加困难。您可以通过引发一些表明命令失败的事件来做到这一点,但直接将某些内容返回给客户端会容易得多。

      【讨论】:

      • 我不同意您的假设To start with, don’t use a bus if you do not need to,因为总线允许将事物与装饰器模式耦合在一起(例如,QueuingCommandBus、TransactionnalCommandBus,都装饰了 BaseCommandBus...)| If you use a bus, then you need to validate your commands before you send them 我让 CommandHandler 验证命令本身的优点,然后验证业务不变量的聚合。
      • 我表达了我的观点,你不应该像我规定的那样使用命令总线。我已经改变了措辞,但我仍然坚持,命令总线不应该是默认选择。
      猜你喜欢
      • 1970-01-01
      • 2015-06-30
      • 2021-05-06
      • 1970-01-01
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      • 2018-05-23
      • 2012-04-30
      相关资源
      最近更新 更多