Yii2中非显而易见的RabbitMQ或为什么RabbitMQ一次写入所有队列


我想分享在Yii2中配置RabbitMQ队列代理的实际问题。 我警告读者,与该队列代理合作时我没有专家意见,但是我真的想填补Yii2文档中的空白,并巩固自己的痛苦。 因此,如果您曾经遇到过将消息发送到队列服务器上所有队列的问题,则表示您同意这是一个问题,并且不了解为什么会发生这种情况,因此,我要求您提供帮助。

为什么会遇到这种行为? 例如,如果您像我一样,以前从未使用过RabbitMQ,但是例如曾与Gearman合作过。 Gearman本身,就像铁路一样简单(是从Internet上著名的和受人尊敬的角色借来的 )。 您创建一个具有特定名称的队列,然后将数据放在该队列中。 工作程序从队列中读取相同的名称。 一切都很简单。 现在是时候使用时尚技术,而无需了解为什么选择RabbitMQ。 然后,您很高兴Yii2为许多流行的队列代理提供了现成的抽象。 不足的文档告诉默认配置以开始一切:

return [ 'bootstrap' => [ 'queue', // The component registers its own console commands ], 'components' => [ 'queue' => [ 'class' => \yii\queue\amqp_interop\Queue::class, 'port' => 5672, 'user' => 'guest', 'password' => 'guest', 'queueName' => 'queue', 'driver' => yii\queue\amqp_interop\Queue::ENQUEUE_AMQP_LIB, // or 'dsn' => 'amqp://guest:guest@localhost:5672/%2F', // or, same as above 'dsn' => 'amqp:', ], ], ]; 

似乎一切都非常简单,这是与queueName熟悉的行,可以复制,粘贴,修复,运行它-可以运行! 我们为系统的其他组件排队。 我们与我们的PHP可以并行化。 提交,Push满意,我们将任务放入QA中,然后去阅读了一份habr( 在午休时间 )。

在这里,最有趣的是,聊天中的质量检查打断了我们,并说正在发生奇怪的事情。 由于某些原因,工作人员(消费方)写入的数据是重复的。 什么什么 不可能是那样。 我们去检查日志。 我们看到消息正在写入队列中,通过该消息正确选择了队列,收到了哈希jobId。 不,不,我们没有错误。 我们正在写满意的QA,请再次检查,这不能,我们做得很好。

从字面上看,半个小时后,我们又分心了,错误再次出现,然后通知传到肥皂上-任务被转移回工作。 好吧,我是一名程序员,现在我们将解决这个问题。 与Gearman不同,RabbitMQ具有Web界面,其中包含有关服务器的大量信息。 这个奇迹看起来像这样:



我们将更多消息发送到队列中,我们在Webmord中看到我们的消息到达并由工作人员处理。 随便看看,当我们将消息放入队列时,“消息速率”图表会跳入所有队列。



我们检查了一百次配置,重新阅读了Yii的不足文档。 我们一切都做对了。 我们去阅读Rabbit网站上的文档。 在黑暗中徘徊了几十分钟之后,我们偶然发现了一个教程 。 在第一段之后,我们立即了解了我们误会的原因-交流。 我不会重复非常简短的文档。

在RabbitMQ中,我们不将消息写到队列中,而是将其写为交换,这是一种代理,它在一端接收消息并在另一端与服务器上的队列进行通信。 他有权决定将数据放入哪个队列。 有趣的是,Yii文档中没有关于此的任何一行。 乍一看,尚不清楚如何配置交换,我们深入探讨了这一点,并在文件供应商/yiisoft/yii2-queue/src/drivers/amqp_interop/Queue.php:176中找到了可以填充的珍贵属性。 在这里我必须说,RabbitMQ有许多驱动程序,在我的情况下使用enqueue / amqp-lib 。 我们设置了exchangeName ,测试,没有任何变化。 好吧,我们就像是一位真正的俄罗斯工程师,首先我们尝试一下,然后再去考虑一下,再次阅读文档。 我们再次仔细阅读,然后转到Rabbit的网络面孔,并看到以下内容:



我们的几个队列与同一交换相关联。 宾果! 这就是原因,一个“但是”,我没有约束它们。 我们再次进入驱动程序的内部,找到setupBroker方法行392

 $this->context->bind(new AmqpBind($queue, $topic)); 

这是非托管绑定。

因此,无需三思而后行,我们得出的结论是,必须为每个队列声明其交换,然后连接将是正确的,并且一个交换将只有一个连接的队列。 这样,我们得到了类似的Gearman行为。 顺便说一下,文档详细描述了为什么进行交换,据我所知,原因之一是能够通过交换链接多个队列。 伙计们在评论中写道,但我没有想到可能需要的情况。 写下,您遇到上述情况还是我做错了一切?

Source: https://habr.com/ru/post/zh-CN439080/


All Articles