2007年,Rabbit技术公司基于AMQP标准开发的RabbitMQ 1.0发布。RabbitMQ采用Erlang语言开发。
Erlang语言由Ericson设计,专门为开发高并发和分布式系统的一种语言,在电信领域使用广泛。
AMQP
AMQP,即advanced Message Queuing Protocol (高级消息队列协议),是一个网络协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端\中间件不同产品,不同的开发语言等条件的限制。2006年,AMQP规范发布。类比HTTP。
MQ的优势与劣势
优势:
- 应用解耦
- 异步提速
- 削峰填谷
劣势:
- 系统可用性降低
- 系统复杂度提供
- 一致性问题
小结:
MQ需要满足什么条件?
- 生产者不需要从消费者获得反馈。引入消息队列之前的直接调用,其借款返回值应该为空,这才让明明下层的动作还没有做,上层却当成动作作完了继续往后走,即所谓异步成了可能。
- 容许短暂的不一致
- 确实是用了有效果。即解耦、提速、削峰这些方面的收益,超过加入MQ,管理MQ这些成本。
MQ常见的产品
RabbitMQ基础架构如下图:
RabbitMQ中的相关概念:
- Broker:接收和分发消息的应用,RabbitMQ Server就是Message Broker
- Virtual host:出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,/以于网 络中的namespace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange / queue等
- Connection: publisher / consumer 和 broker 之间的 TCP 连接
- Channel:如果次访问 RabbitMQ 都建立一个Connection,在消息量大的时候建立TCP Connection的开销将是巨大的,效率也较低。Channel是在connection内部建立的逻辑连接,如果应用程序支持多线 程,通常每个thread创建单独的channel进行通讯,AMQP method包含了channel id帮助客户端和 message broker识别 channel,所以channel之间是完全隔离的。Channel作为轻量级的Connection 极大减少了操作系统建立TCP connection的开销
- Exchange: message到达broker的第一站,根据分发规则,匹配查询表中的routing key,分发消息到 queue 中去。常用类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)
- Queue:消息最终被送到这里等待consumer取走
- Binding: exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key。Binding 信息被保存到exchange中的查询表中,用于message的分发依据
RabbitMQ提供6种工作模式:
- 简单模式
- work queues
- publish\subscribe发布与订阅模式
- Routing路由模式
- Topics主题模式
- RPC远程调用模式(远程调用,不太算MQ)
RabbitMQ高级特性
消息的可靠性
- 持久化
- exchange要持久化
- queue要持久化
- message要持久化
- 生成方确认Confirm
- 消费方Ack
- Broker高可用
消费端限流
确保ack机制为手动模式
TTL
- 可以设置队列过期,队列过期,会清除队列中所有消息
- 可以设置消息过期,消息过期后,只有在队列顶端,才会去判断其是否过期(过期移除)
队列和消息都设置了过期时间,以时间段的设置为准
死信队列
英文缩写:DLX。Dead Letter Exchange(死信交换机),当消息成为Dead Message后,可以被重新发送到另一个交换机,这个交换机就是死信交换机。
死信交换机和死信队列和普通的交换机和队列没有区别
Dead Message来源:
- .队列消息长度到达限制;
- 消费者拒接消费消息,basicNack/basicReject并且不把消息重新放入原目标队列,requeue=false;
- 原队列存在消息过期设置,消息到达超时时间未被消费; .
需要队列绑定到死信交换机:
延迟队列
消息进入队列后不会被立马消费,只有达到指定时间后,才会被消费。
TTL+ 死信队列 实现延迟队列效果
消息跟踪
在使用任何消息中间件的过程中,难免兔会出现某条消息异常丢失的情况。对于RabbitMQ而言,可能是因为生产者或消费者与RabbitMQ断开了连接,而它们与RabbitMQ又采用了不同的确认机制;也有可能是因为交换器与队列之间不同的转发策略;甚至是交换器并没有与任何队列进行绑定,生产者又不感知或者没有采取相应的措施;另外RabbitMQ本身的集群策略也可能导致消息的丢失。这个时候就需要有一个较好的机制跟踪记录消息的投递过程,以此协助开发和运维人员进行问题的定位。
在RabbitMQ中可以使用Firehose和rabbitmq_ tracing插件功能来实现消息追踪。
消息应用问题
消息可靠性保障
消息补偿机制
消息幂等性保障
乐观锁解决方案
幂等性指一次和多次请求某一个资源, 对于资源本身应该具有同样的结果。也就是说,其任意多次执行对资源本身所产生的影响均与-次执行的影响相同。
在MQ中指,消费多条相同的消息,得到与消费该消息一次相同的结果。
集群创建
通过集群镜像队列同步数据+负载均衡(haproxy)