关于AMQP通道处理的最佳实践问题我已经迷惑了很久了。本文中,我尝试阐述了我现在的想法,同时也期待获得读者的反馈。
消息代理服务器和客户端之间的会话是双向的。客户端和服务器都可以创建‘通信事件’;客户端可以调用服务器上的方法: 比如说‘publish’ 或‘declare’;而服务器也可以调用客户端上的方法,比如‘deliver’或者‘reject’。由于客户端需要从服务器获取方法,所以它需要在其生存期内一直保持连接的开放状态。这意味着连接可能会持续较长时间;几小时,几天或者几周。不管对客户端还是服务器来说,保持这些连接是很耗费资源的。为了在不使用大量的物理TCP/IP连接的情况下就能拥有大量的逻辑连接,AMQP使用了‘通道(channel)’ 的概念(在其Java and .NET客户端的IModel接口中有较为模糊的描述)。你可以在单个连接中创建多个channel,相对来说创建和销毁它们的代价要小的多。
那么关于如何处理这些通道,有什么推荐规则吗?我每次操作都应该创建一个新的通道吗?或者,我应该只维持一个通道并且每一个方法都通过它来执行?
首先是一些硬性规则(注意这里我参考的是RabbitMQ的.NET客户端,其它客户端可能会有不同的行为):
通道不是线程安全的。 你应该在每个线程中都创建一个通道。下面这段话来自.NET客户端的文档(2.10章节):
“通常来说,IModel实例不应当被多个线程并发使用: 关于IModel 实例的线程所有权,应用程序代码应当有清晰的概念。”
很明显在Java客户端中这不是一个硬性规则,只是一个好建议。java客户端把所有调用都串行化安排给一个通道。
不要把发布和消费混为一谈。如果你能按照上面的建议做,这就意味着你将创建很多通道服务于每一个用户。这将让你为服务端和客户端创建独立的通道。
维护一个长时间发布通道。最近我实现了EasyNetQ,它可以为用户发布信息而创建通道。现在我认为这是个错误。这里的模式是:创建通道,发布,销毁通道。这个模式在当发布者要确认 需要保持通道打开直到你收到ACK或NACK时工作的不好。尽管创建个通道是很轻的,但仍然需要消耗的。现在我致力于在一个工作线程中和在一组发布(并宣布)中维护一个单发布通道。这有潜在的瓶颈,但是令人映象深刻的是其非事务性的发布意味着我不是过分的关注它。
评论删除后,数据将无法恢复
评论(1)