它在RabbitMQ文档中声明了以下内容 “根据经验,在线程之间共享Channel实例是 要避免的事情。应用程序应该更喜欢使用频道 …
您引用的文档适用于Java客户端。你应该指的是 这个文件 代替。
您正在使用最新版本的.NET客户端( 5.1 ),所以做你的工作 Received 事件处理程序不会阻止处理TCP数据的其他线程,也不会阻止心跳 - 两者都很好。
5.1
Received
首先,打电话 channel.BasicQos(0, 1, false) 意味着您的消费者一次只能从RabbitMQ收到一条就绪消息,直到 BasicAck 被称为另一个消息将不会被传递。所以,没有理由在另一个线程中完成你的工作,因为你无论如何都不会得到另一个消息。
channel.BasicQos(0, 1, false)
BasicAck
如果您增加预取值(通过实验和运行基准测试),如果您的工作运行时间超过几毫秒,则必须在后台线程中完成工作。
当你在工作时 Received 事件回调,它将阻止用于进行回调的线程,因为回调没有在自己的线程上执行。因此,您可以确保您的工作很短,或者在另一个线程中完成工作。
我只是花了一些时间来审查.NET客户端代码,我很确定 IModel 实例不是线程安全的。如果你增加预取,你将有机会同时确认几条消息,所以我建议实现一个使用它的解决方案,并确保 BasicAck 在创建连接的同一线程上调用。
IModel
<子> 注意: RabbitMQ团队监控 rabbitmq-users 邮件列表 并且有时只回答StackOverflow上的问题。 子>
rabbitmq-users
资源: https://www.rabbitmq.com/api-guide.html
使用手动确认时,重要的是要考虑 什么线程确认。如果它不同于 收到交付的线程(例如Consumer#handleDelivery 委托交付处理到另一个线程),承认 多个参数设置为true是不安全的,将导致 双重确认,因此是一个通道级协议 关闭频道的例外。确认单个消息 时间可以安全。
channel.basicAck(tag, false) 是线程安全的
channel.basicAck(tag, false)
但 consumerChannel.basicAck(tag, true) 不是。
consumerChannel.basicAck(tag, true)
还提到了一些好处 RabbitMQ和渠道Java线程安全