RabbitMQ在项目中的使用方式+简略介绍

声明:文章写于2016-11-10,项目中RabbitMQ的使用方式在后面可能会发生变化。

消息队列(MessageQueue)的好处:

  • 简化业务流程
  • 异步处理消息
  • 减少组件耦合
  • 消减数据峰值

消息队列的应用场景:

  • 场景1:
    支付成功以后,给用户发送优惠券or红包;
  • 场景2:
    用户注册成功后发送通知邮件or短信;

  • 场景3:
    活动里面的站内信发送;
    . . . . . .
    总结起来就是,把单个业务简洁化,通过消息系统把不相关的业务连接起来,实现更复杂的业务链,降低整个系统的复杂度。

安装

安装方法自行google,如果要在生产环境中安装请先联系运维,涉及到安全问题。

项目中使用

//发布消息
use CI123\Shop\Tool\RabbitMq\Publisher;
Publisher::publish('routing_key', $message);

//监听消息
use Api\Tool\RabbitMq\Subscriber;
Subscriber::subscribe('routing_key', function ($msgObj)    {
            $message = $msgObj->body;
            Subscriber::ack($msgObj);
});

以上是对RabbitMQ极其简陋的介绍,下面是重点:

一、我们项目中怎么设置RabbitMQ的:

1. 持久化

真正的持久保存消息,需要设置三个地方:
1.1 将交换机设置成durable;
1.2 将队列设置成durable;
1.3 将消息的delivery_mode设置成2;

PS:
缺少任何一个设置,都无法真正持久化;
持久化会消耗额外的性能;

2. 自动删除

2.1 消息在队列里存在时间是5分钟;
2.2 队列本身存在时间是30分钟;
2.3 过期的消息会被移出到“死信队列”;
2.4 死信队列里的消息存在7天;
2.5 死信队列本身存在10天;

3. 消费者应答机制(ack/nack机制)

3.1 如果消息已经被正确消费了,你可以通过ack方法告诉rabbitmq,rabbitmq会删除这条消息;
3.2 反之,你可以调用nack告诉RabbitMQ消费失败,rabbitmq会立马将消息移到“死信队列”;
3.3 或者什么都不做,等待消息过期后被移动到“死信队列”。

4. 生产者确认机制(Confirm机制)

4.1 发布消息后,发送者可以通过异步的回调知道消息是否发送成功;

PS:目前项目中基本没有使用。

二、初步理解RabbitMQ

1. 四个比较重要的概念

  • 虚拟主机(vhost):每个vhost都有单独一套交换器、队列、绑定规则
  • 交换器(exchange):将消息发送到队列
    常见相关名词:
    + 名称(exchange):交换器名字,不能重复
    + 类型(type):fanout/direct/topic/headers
    + 持久化(durable):服务重启后是否要恢复
    + 自动删除(auto-delete):没有队列使用交换器时自动删除
  • 队列(queue):存取消息
    常见相关名词:
    + 名称(queue):队列名字,不能重复
    + 持久化(durable):服务重启后是否要恢复
    + 自动删除(auto-delete):没有消费者时自动删除
    + 声明(arguments): 消息存在时间(x-message-ttl)、队列存在时间(x-expires)
  • 绑定(binding):将队列和交换机绑定,以通过routing_key来收发消息;

2. 四种Exchange

  • fanout :广播
  • direct:routing_key全部匹配
  • topic:可以理解为在direct的基础上给routing_key增加了正则匹配,当然肯定不是正则;
  • headers:消息里包含headers,如果消息的headers和队列能匹配上就将消息投递到该headers,可以指定是完全匹配(all)还是只需要匹配单个(one);

3. 其他概念和结论

  • 消息的获取有主动拉取、被动接收,发布/订阅模式是被动接收;
  • 交换器、队列的属性一旦声明就不可更改,但是绑定是可以解绑的(unbind);
  • 当一个 message 被路由到多个 queue 中时,在某个 queue 中的某个 message 的“死亡”不会对相同 message 在其他 queue 中的生存状况;
  • 同时设置了队列生存时间T1和消息生存时间T2后,消息在队列中的存在时间是T1/T2之中的最小值;
  • 如果没有设置死信队列,即便你设置了durable,消息到期后也会被丢弃;

4.目前的使用状况

  • 按照普通的消息队列来使用:佣金、理财、保险;
  • 改造为延时队列:微信模板消息,通过延时队列来重发上次发送失败的消息;
  • 可以改造为任务队列使用:待定;

发表评论