你的系统里为何用Kafka?
1 消息引擎是啥?
较于“消息队列”“消息中间件”,消息引擎系统可能更合适,因为消息队列给出了一个很不明确的暗示,仿佛Kafka是基于队列构建的;而消息中间件说法有过度夸张“中间件”之嫌,让人搞不清楚这个中间件到底干啥的。
Kafka这种系统在国外有专属名字 - Messaging System,国内很多文献将其简单翻译成消息系统,这片面强调消息主体的作用,而忽视了这类系统引以为豪的消息传递属性,就像引擎一样,具备某种能量转换传输的能力,所以消息引擎更加贴切。
2 这类系统有啥用?
消息引擎系统是一组规范。企业利用这组规范在不同系统之间传递语义准确的消息,实现松耦合的异步式数据传递。
系统A发送消息给消息引擎系统,系统B从消息引擎系统中读取A发送的消息
最基础的消息引擎就是做这事:
- 消息引擎传输的对象是消息
- 如何传输消息属于消息引擎设计机制的一部分
既然消息引擎是用于在不同系统间传输消息,那
3 如何设计待传输消息的格式?
一条消息如何才能做到信息表达业务语义且无歧义,同时还能最大限度提供可重用性以及通用性?
使用成熟解决方案?比如CSV、XML、JSON,又或国外大厂开源的一些序列化框架,比如Google的Protocol Buffer或Facebook的Thrift。而Kafka使用纯二进制字节序列。当然还是结构化的消息,只是在使用前都将其转换成二进制字节序列。
消息引擎系统还要设定具体传输协议
4 如何传输消息?
4.1 点对点模型
也称消息队列模型。系统A发送的消息只能被系统B接收,其他任何系统都不能读取A发送的消息。
比如电话客服:同一客户呼入电话只能被一位客服人员处理,其它客服人员不能为该客户服务。
4.2 发布/订阅模型
新增主题(Topic)概念,即逻辑语义相近的消息容器。该模型的发送方也称发布者(Publisher),接收方为订阅者(Subscriber)。
和点对点模型不同,该模型可能存在多个发布者向相同的主题发消息,而订阅者也可能存在多个,它们都能接收到相同主题的消息。
比如生活中的报纸订阅就是一种发布/订阅模型。
而Kafka同时支持俩种消息引擎模型哦!
5 消息引擎系统 V.S JMS
JMS,Java Message Service,也同时支持两种消息引擎模型。严格说它并非传输协议而仅仅是API。不过JMS太有名以至于很多主流消息引擎系统都支持JMS规范,比如RabbitMQ、Kafka。Kafka也未完全遵照JMS规范。
6 为什么要使用消息引擎?
为什么系统A不能直接发送消息给系统B,中间还非得隔个消息引擎?
为了削峰填谷:
即缓冲上下游瞬时突发流量,使其更平滑。特别是对于那种发送能力很强的上游系统,若无消息引擎保护,“脆弱”的下游系统可能会直接被消息流量压垮导致服务雪崩。
有了消息引擎,就能够有效对抗上游流量冲击,将上游的“峰”填满到“谷”,避免流量震荡。
消息引擎系统的另一大好处在于发送方和接收方的松耦合,这也在一定程度上简化应用开发,减少系统间很多不必要的交互。
Kafka具体又是怎么“抗”峰值流量呢?
- 比如你在外需要开房预订酒店,每家酒店都有专门预订按钮
点击之后进入到付费页面。这简单流程就包含多个子服务,比如点击预订按钮会调用订单系统生成对应订单,而处理该订单会依次调用下游的多个子系统服务 ,比如调用支付宝和微信支付的接口、查询你的登录信息、验证酒店信息等。上游订单操作比较简单,其TPS远高于处理订单的下游服务,因此上下游系统直接对接,势必会出现下游服务无法及时处理上游订单从而造成订单堆积。特别秒杀时,上游订单流量瞬时增加,可能直接压跨下游子系统服务。
对上游系统限速?这种做法对上游系统而言显然不合理,毕竟问题并不出现在它。所以更常见的办法是引入像Kafka这样的消息引擎系统来对抗这种上下游系统TPS的错配以及瞬时峰值流量。
引入Kafka后。上游订单服务不再直接与下游子服务交互。当新订单生成后它仅仅是向Kafka Broker发一条订单消息。下游的各个子服务订阅Kafka中的对应主题,并实时从该主题的各自分区(Partition)中获取到订单消息进行处理,从而实现上游订单服务与下游订单处理服务解耦。当秒杀时,Kafka能将瞬时增加的订单流量全部以消息形式保存在对应主题,既不影响上游服务的TPS,同时也给下游子服务留出了充足的时间去消费它们。这就是Kafka这类消息引擎系统的最大意义。
7 MQ V.S RPC
广义上属于数据流模式(dataflow mode)区别。
常见数据流:
- 通过数据库
- 通过服务调用(REST/RPC)
- 通过异步消息传递(消息引擎,如Kafka)
RPC和MQ相似,远程调用一个服务也可看做是一个事件,但不同在于:
- MQ有自己的buffer,能够对抗过载(overloaded)和不可用场景
- MQ支持重试
- 允许发布/订阅模式
当然它们还有其他区别。应该说RPC是介于通过DB和通过MQ之间的数据流模式。
参考
- Apache Kafka实战