Mq vs Rpc ?11个角度的对比

2023年 9月 25日 91.0k 0

MQ和Rpc并无优劣,但是在不同的使用场景,需要具体问题具体分析使用哪种方式。
image.png

image.png

1. 调用端关注调用结果,实时性强的场景,使用 rpc还是mq?

例如创建资源流程一般会对流程参数进行校验,如果参数不合理,则返回创建失败和具体的错误码、错误信息等,创建成功需要返回创建结果例如资源的唯一Id等。因为生产者发送完MQ消息并不知道消费者消费MQ的状态,更无法获知消费结果,所以这个场景并不适合Mq。rpc更适合这个场景,是因为被调用端通过定义Rpc接口,规定了请求入参和出参的格式,调用端像是调用本地方法一样调用服务端方法。

例如业务系统调用短信平台发送短信,就不适合使用MQ。这是因为短信平台会校验短信模版和短信参数是否一致,是否正确,校验短信长度是否符合要求,并告知调用端校验结果。相比Mq,Rpc恰恰更适合这个场景。

由于发送短信接口耗时比较高,使用Rpc可能会导致阻塞调用端。服务端可以在校验完成短信请求后,落库存储,使用MQ或线程池异步发送短信。

MQ和Rpc并无优劣,更多时候需要互相配合,需要根据实际场景选择合适的方案。

2. 查询场景使用rpc还是mq?

因为查询场景调用端必定关注调用结果,所以查询场景,只能使用Rpc,不能使用MQ。不再多说。

3. 异步调用场景,使用Rpc还是mq?

MQ天然支持异步,生产者发送消息成功即刻返回。消费者异步从消息队列推拉方式消费消息。 所以异步场景 MQ天然适合。那Rpc就不可以异步调用吗?

实际上各种Rpc框架都支持异步调用,共体现在三个地方

  • 业务线程把Rpc请求任务丢到线程池
  • Rpc 使用Netty NIO方式,使用非阻塞式IO,发送消息和处理请求时,不阻塞IO线程。
  • Rpc被调用端异步处理,把消息丢弃到线程池处理。
  • 虽然Rpc支持异步处理请求,但是相比MQ而言,更加复杂。不如MQ天然支持异步处理

    在这个场景,MQ更胜一筹

    4. 发布订阅模式,新增消费组时,生产者无需关注

    当有多个潜在消费者关注时,如果使用Rpc,就需要调用端逐个调用生产者,需要使用线程池异步并行调用多个服务者进行处理,并且需要处理超时、处理失败、耗时高等场景。实现较为复杂。 更重要的是,生产者系统并不关心消费者,为什么要修改生产者所在系统呢?

    MQ更适用用这个场景。生产者将消息发送到消息队列后,就不再需要关心消息的处理结果。消息的可靠性投递、重试等特性都是消费队列实现。增加一个消费者,只需要在消息队列申请新的消费组即可。生产者系统无需任何改动。

    在实际应用中,像订单状态变更消息,有大量消费者订阅,有大量的业务逻辑基于订单状态,通过MQ作为中间层,解耦了订单系统和下游系统。很难想象,如果是rpc依赖,订单系统要感知多少个下游,一个订单事件,要rpc通知多少个下游。

    5. MQ支持广播模式

    MQ除了支持一个Topic被多个应用服务、多个消费组消费,也支持将消息广播到每一个消费者实例。例如websocket场景,由于浏览器端websocket连接只能和一个服务端实例连接,所有发给这个socket实例的消息都要转发到这个服务端实例。简单的办法就是通过消息队列先广播给所有的服务器实例,然后服务端查询自己是否管理相关的websocket连接。 其他场景包括缓存数据同步、缓存失效等。都可以通过消息广播实现。rpc并不适用这个场景。

    6. Mq接口格式更加灵活

    一般情况下Rpc接口通过IDL或者Java/C++等语言定义,服务端需要实现该接口实现,调用端也需要引用接口依赖。而MQ在这方面更加灵活,生产者和消费者无需强依赖接口定义,两者只需要遵循相同的格式即可。例如定义消息的JSON格式,生产者和消费者按格式解析即可。

    MQ相比Rpc在接口格式上更加灵活,如果希望上下游接口依赖更加灵活,可以考虑使用MQ

    MQ可解耦生产者消费者,一般就是指

  • 生产消费速度解耦
  • 无需接口强依赖
  • 异步调用解耦
  • 订阅发布模式下新增消费组无感知等特性。
  • 下面讨论消息队列在性能和稳定性上的优势。

    7. MQ具备存储能力

    消息投递到消息队列,会被可靠的存储,可以提供可视化页面提供消息列表查询能力,也可以通过数据通道工具,将kafka消息异构到Hive中,提供离线数据统计的能力。
    同时MQ可提供消费端重新消费、回溯历史消息的能力,消费过程中存在异常,可以有效保证重试消费。最大程度保证处理流程的最终一致性。

    MQ的存储能力相比Rpc 更强。

    8. 使用MQ和binlog实现数据核对

    MQ消费端涉及到数据库操作会产生binlog,通过关联MQ和 binlog,可以发现处理失败的case。数据比对任务可以核对MQ和Binlog消息,在一个窗口期如果未关联上,说明这条消息处理出现问题。

    把MQ消息离线同步到Hive,数据库同步到Hive中,还可以实现MQ消息和数据库的离线数据核对。

    Rpc因为不具备存储能力,无法关联Rpc请求到binlog,自然无法实现数据正确性核对能力。

    在数据正确性核对上,MQ更优

    9. Rpc & MQ谁的可靠性更高

    如何处理写请求的失败和超时是业务上必须思考的问题。一般情况下业务只需要保证最终一致性,通过重试可以有效解决超时和写失败的问题。

    Rpc如何实现重试呢?可通过Spring-Retry框架,设置间隔时间、重试次数等参数进行重试。如果Rpc重试期间遇到服务发布、宿主机重启等问题,重试会中断,所以这种重试方式并不可靠。

    MQ可以通过ack机制,多次消费同一条消息,重试多次依然失败,还可以投递到对应的死信队列,稍后继续重试和人工处理。消息队列有多种机制可以保证消费成功。消费者服务发布、宕机等因素也不会导致消息丢失、消息无法消费等情况发生。

    相比Rpc,MQ在写场景可以更安全的重试,在可靠性上更强!

    10. MQ & Rpc 吞吐量上谁更高

    消息队列可以解决生产者和消费者速度上的差异,当生产者速率超过消费者速率时,消息会积压在消息队列,消费者可以根据服务的容量调整消费速率。 因为消息队列的存在,当消费者速率低时,不会拖累生产者。如果时Rpc同步调用,生产者因为消费者的低速率消费,大量线程会被阻塞,从而降低生产者的处理速度。

    例如结算场景处理订单的支付完成消息,可以通过MQ解耦。结算场景不会影响C端用户的体验,结算处理的实时性要求并不高。在流量高峰期,结算处理可能赶不上订单支付速度,如果使用Rpc,结算性能瓶颈会降低C端用户交易链路的稳定性。

    MQ的存储能力可以弥补消费端和生产端的消费速率之差,通过消息队列作为中间缓冲,可以削峰填谷,避免瞬时大量请求导致下游过载崩溃,避免两端速率之差导致的服务雪崩风险。

    使用同步Rpc,系统的吞吐量受限于木桶最短的一侧。使用MQ解耦,则最大程度提供系统的吞吐。

    11. 消费端吞吐量的提升

    Rpc服务端无法对多个rpc请求合并然后批量处理,但是MQ消费端可以使用pull拉取模式,批量拉取一批数据,将单次请求转为批量请求,可以有效提高处理速度。

    综上来看,在查询场景、实时获取调用结果的写链路比较适合适用Rpc。在异步、实时性低、无需关注调用结果、多个订阅者的场景,优先使用MQ更为合理。

    总结

  • 调用端关注调用结果,实时性强的场景,Rpc更优
  • 查询场景只能使用Rpc
  • 异步调用场景,Rpc和MQ均可
  • 存在多个订阅者场景,更适合使用MQ
  • 需要广播的场景,适合MQ
  • MQ接口格式更加灵活
  • MQ具备存储能力,可以基于MQ和binlog进行数据正确性核对。
  • MQ处理消息可安全重试,可靠性更强
  • MQ作为缓冲,可以削峰填谷,弥补生产消费两端的速率之差,避免系统雪崩
  • MQ通过批量拉取批量消费,可以有效提升系统吞吐量。
  • 相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论