开发前的规范

1. 一个 RabbitMQ 应用里建立多个 vhost,去对应不同的开发项目

我们在使用数据库的时候,会在一个数据库应用里建立多个不同的数据库去给不同的项目使用,而不用在不同的服务器专门每个项目都安装个数据库应用。
在 RabbitMQ 的 vhost,也是类似的理念。

vhost 本质上是一个 mini 版的 RabbitMQ 服务器,拥有自己的队列、绑定、交换器和权限控制,当在 RabbitMQ 中创建一个用户时,用户通常会被指派给至少一个 vhost,并且只能访问被指派 vhost 内的队列、交换器和绑定。

vhost 之间是绝对隔离的。
所以,不同的 vhost 对应不同的项目,互不影响,而这些 vhost 其实都是在一台主机一个 RabbitMQ 应用上。
但是,现在的状况是大部分使用 RabbitMQ 的技术团队往往就使用默认的 vhost:“/”,如果多出一个项目了,就再去创建一个 RabbitMQ 的进程。这样做,非常浪费开发资源。

推荐一个项目对应一个 vhost。

2. 不直接使用 RabbitMQ 自己的客户端

**
很多公司使用 RabbitMQ 都是直接使用 RabbitMQ 自己的 java 版本客户端,但是由于 RabbitMQ 本身内在的复杂性和多样性,有很多技术细节需要独自处理。
比如网络连接的处理,比如异常的处理,比如消息失败的处理等等等。这些,如果手头没有一套成熟的框架,那么很可能由于一些细节处理不到位,导致非常多的问题,这都是不必要的成本。
所以,要么使用一套已有的 RabbitMQ 客户端框架(比如 Spring 的 RabbitMQ 框架),要么自己封装出一套底层 RabbitMQ 客户端框架,而不是单独使用 RabbitMQ 的客户端

3. 无论如何消费者必须给回 ACK 响应

ACK 机制就是消费者从 RabbitMQ 收到消息并处理完成后,反馈给 RabbitMQ,然后 RabbitMQ 收到反馈后才将此消息从队列中删除。

由于 ACK 机制本身必须回复给 RabbitMQ,消息才会丢弃这个特点。
对于何时给 ACK,我们做开发的时候一定要在开发项目前提前规划好、设计好。
我们使用 RabbitMQ 通常不想在收到消息就立即给回 ACK 的,也不会设置 autoACK 机制即消费端收到自动返回一个 ACK 响应。一般来讲,我们都会根据业务逻辑的不同,会在不同的位置手动返回 ACK。

这时候,就可能出现问题:当收到消息,有时候处理业务逻辑报错了,往往在处理完业务逻辑就会忽略 ACK,这会导致消息始终卡死在 queue 里……如果数量越来越多,后续处理非常麻烦。

4、考虑设置 dead letter exchanges

我们得知道,有时候消息投递出错,并不总是在应用接收的时候出了问题,会有很多非应用的问题。比如:

  1. 消费端有问题,发出的消息被拒绝了。并且我们也设置了 requeue=false;
  2. 消息可能因为没有收到 ACK 超时被删除,或者消费端消费速度跟不上导致消息超时被删除;
  3. 消息数量超过了队列最大长度限制被抛弃;
  4. 消息总大小超过了队列消息总大小限制被抛弃。

对于这些问题,设置 dead letter exchanges 算是一个解决办法。当消息一旦出现我上面列举出来的情况,就会被发送到我们设置的 dead letter exchanges。然后我们就可以对这些特殊情况的消息进行单独处理,这样的做法可以让我们的项目更健壮,更容易追踪问题。
**

5. 尽量使用 Direct Exchange

RabbitMQ 的Exchange 就是消息交换机,它指定消息按什么规则,路由到哪个队列。

有四种类型:

  1. Direct:处理路由键,需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键为“green”,则只有路由键为“green”的消息才被转发,不会转发路由键为”red”,只会转发路由键为“green”。

  2. Topic:将路由键和某模式进行匹配。此时队列需要绑定要一个模式上。符号“#”匹配一个或多个词,符号“*”只能匹配一个词。

  3. Fanout:不处理路由键。你只需要简单的将队列绑定到交换机上。一个发送到该类型交换机的消息都会被广播到与该交换机绑定的所有队列上。

  4. Headers:不处理路由键,而是根据发送的消息内容中的 headers 属性进行匹配。在绑定 Queue 与 Exchange 时指定一组键值对;当消息发送到 RabbitMQ 时会取到该消息的 headers 与 Exchange 绑定时指定的键值对进行匹配;如果完全匹配则消息会路由到该队列,否则不会路由到该队列。

在这四种类型里,Direct 类型的 Exchange 投递消息是最快的。其他的 Exchange,MQ 还得花时间计算投递的位置。所以,能使用 Direct 类型的建议使用 Direct。

  • 开发中的注意事项;
  • 以及 MQ 本身的优化。