工作中用过一段时间的 Kafka,不过次要还是 RabbitMQ 用的多一些。明天次要来讲讲与 RabbitMQ 相干的一些常识。一些基本概念,以及理论应用场景及一些注意事项。
1 基本概念
RabbitMQ 应用 Erlang 开发,实现了高级音讯队列协定(AMQP),同时还反对 MQTT、STOMP 等。
1.1 外围概念
- Broker: 音讯队列服务主机
- Exchange: 音讯交换机,可依照特定规定将音讯路由到具体队列 (上图
X
即为交换机) - Queue: 音讯队列,每个音讯实践都要被投入到一个或多个队列 (上图红色矩形即为队列)
- Binding: 绑定关系,将
Exchange
和Queue
依照某个路由规定进行绑定 - RoutingKey: 路由关键字,
Exchange
依据该 Key 进行不同的路由 - Vhost: 虚拟主机,在同一物理主机上做资源逻辑隔离,相似
命名空间?
- Connection: 客户端与主机建设的 TCP 连贯
- Channel: 音讯通道,同一
Connection
能够有多个Channel
,每个Channel
都有一个惟一 ID
1.2 交换机
按类型分四种:Direct Exchange,Topic Exchage,Fanout Exchange,Headers Exchange
1.2.1 Direct Exchange
间接交换机,在没简单路由场景时,这种路由器应用的较多。特点是 严格 RoutingKey
路由。只有当 RoutingKey
完全一致时,才会明天路由投递。
1.2.2 Fanout Exchange
播送交换机,一个音讯须要无差别投递到所有绑定的队列中时。无需设置RoutingKey
,即便设置了也不会失效。
1.2.3 Topic Exchange
主题交换机,相似间接交换机。不同的是能够依据 RoutingKey
进行含糊匹配 (#
示意一个或多个单词,*
示意一个单词)。
这样来看的话。
- 当不应用
#
或*
进行含糊匹配时,它跟Direct Exchange
仿佛没啥区别。 - 当仅应用
#
进行含糊匹配时,它跟Fanout Exchange
仿佛也没啥区别。
能够看到:
Q1
能够匹配:x11.orange.x22
,但无奈匹配x00.x11.orange.x22
。Q2
能够匹配:lazy.orange
,也能匹配lazy.orange.rabbit
。
1.2.4 Headers Exchange
申请头交换机,不应用 RoutingKey
路由,依据音讯头中的 key-value
属性进行路由。
能够通过设置 x-match: any
、x-match: all
来进行 or
、and
逻辑匹配。
1.2.5 其余属性
- Durability: Durable(长久的),Transiant(短暂的)。
- Auto delete:当有队列或交换机绑定了本交换机,在队列或者交换机都又进行理解绑后,主动删除
- Internal: 是否为外部应用。true 示意为外部交换机,客户端无奈间接向该交换机发送音讯。
-
Arguments:
- alternate-exchange: 备份交换机,当音讯无奈路由到具体队列时,将交给备份交换机解决。
1.3 队列
音讯只能存在于队列中,上面看一下队列都有哪些属性。
- Type: Classic,Quorum
- Durability: Durable(长久的),Transiant(短暂的)
- Auto delete: 当有消费者订阅,而后所有的消费者又都断开连接,则主动删除
-
Arguments:
- x-message-ttl:
Message
在Queue
中存活工夫,超时将被抛弃 - x-expires:
Queue
在没有被应用的状况下,过期工夫 - x-max-length:
Queue
中能够寄存的最大音讯数,超过将被抛弃 - x-max-length-bytes:
Queue
中能够寄存最大音讯体大小,超过将被抛弃 - x-overflow:
Queue
溢出后的行为,drop-head
、reject-publish
、reject-publish-dlx
。 - x-single-active-consumer: 确保只有一个消费者订阅,当出现异常时主动转向另外一个。
- x-max-priority: 队列反对的最大优先级,不设置将不反对。
- x-dead-letter-exchange: 当
Message
被rejected
或expire
时,将会被从新公布到哪个交换机。 - x-dead-letter-routing-key: 当成为死信时,应用的
RoutingKey
,未设置时则应用原始Key
。 - x-queue-mode: 当设置为
lazy
时,会将音讯尽可能的搁置到磁盘上,以缩小内存应用。 - x-queue-master-locator: 将队列设置为主节点定位模式。
- x-message-ttl:
2 应用场景
利用场景个别为三类: 异步、解耦、削峰填谷。
2.1 异步
异步个别是指: 同一个零碎内,应用队列将申请和响应异步化,不阻塞主线程,从而取得更高的处理速度,以晋升零碎性能。
最早在做商城我的项目时。用户下单付款后先更新本地订单记录,而后再向第三方物流零碎推送待发货音讯、向用户发放订单相干站内信、并可能触发积分赠送及推荐人的返利计算、以及可能触发相干营销规定发放优惠券等操作。
2.2 解耦
解耦个别指: 不同零碎间,通过队列形式进行通信,使零碎间不至于适度依赖,缩小零碎间耦合性。
在最近的我的项目中,有做的一个事件上报零碎,其实就是各个系统都接入。每个零碎即可做生产者、也能够做消费者。比方用户在下单后,须要给推荐人赠送积分、向内部 CRM 同步商机已成单状态等。
2.3 削峰填谷
削峰填谷个别指: 利用队列作为缓冲,将短时大流量缓存起来,由消费者来决定处理速度。使得零碎负载趋于平稳,从而进步零碎稳定性。
在做用户增长业务相干,用户由落地页提交数据至外部零碎,外部零碎会将数据简略解决后推送到内部 CRM 零碎,销售在跟客户沟通后,会将线索转换为商机。在这个转换过程中,会由 CRM 向外部零碎推送数据。外部零碎会依据传递过去的数据进行各种操作,如创立、更新家长,创立、更新学生,以及各种附加业务信息等。
3 常见问题
3.1 音讯反复问题
音讯反复的场景很多,比方零碎出错、调用超时重试机制、音讯生产异样时 ReQueue
操作等状况。很多时候为了保障音讯的牢靠传递,会保障音讯at-least-once
。这种状况下根本无奈保障不反复发送,所以生产端要保障幂等性。
既然提到重复性,必然要有反复的根据。比方订单号,同一零碎内不容许反复。
- 可借助数据库的
惟一索引
,也可借助 Redis 来保证数据惟一。 - 如果没有反复根据,只能大略依据参数值按肯定规定做哈希解决,不过这种可能存在误判和漏判问题。
3.2 音讯沉积
生产沉积,无非就是生产速度赶不上生产速度。产生的起因有很多,消费者异样呈现生产变慢问题、生产者突发大流量等状况。
解决方案要同时思考生产者和消费者。产生沉积时,将局部生产者降级,敞开非核心业务,缩小音讯产生。消费者优化性能,将沉积音讯长期转移至新队列,启用新的消费者去生产。
3.3 音讯失落问题
从整个流程思考,生产者、队列、消费者三方面。
- 生产者: 保障音讯胜利推送到队列。
- 队列: 保障已推送到队列中的数据不会失落。
- 消费者: 保障已生产的数据被正确处理。
4 后记
零碎设计没有银弹。在引入一个中间件时,要综合思考、权衡利弊。引入中间件,能解决一些问题,但可能会带来更多的问题。
做好系统监控,像生产沉积有些场景下是可预知的,比方长期做流动或者高价促销之类造成的订单激增。而有些像系统故障类,无奈提前预知,则须要监控零碎做到及时告警,提前染指解决。
echo '5Y6f5Yib5paH56ugOiDmjpjph5Eo5L2g5oCO5LmI5Zad5aW26Iy25ZWKWzkyMzI0NTQ5NzU1NTA4MF0pL+aAneWQpihscGUyMzQp' | base64 -d