在微服务中是用队列好还是 RPC 好

2019-07-04 18:11:01 +08:00
 springmarker

个人浅薄的认识,在大多数场景下可以用队列替换 RPC(指代通常的 RPC,不是由队列实现的 RPC)。
队列的优点:
1.消息可以堆积,只要队列稳定,消息丢失的概率就比直接 RPC 低。
2.由接收端主动获取消息的话,负载就由接收端控制了,不会像 RPC 一样无法均衡的负载。
3.没有类似 Zookeeper 的注册中心,发送端和接收端只要面对队列就可以,发送端不用同时面对注册中心和多个接收端。

缺点的话就是性能不如直接 RPC、需要手动写异步转同步。

我看很多微服务都用的是 GRPC 和 Dubbo 之类的 RPC,甚至 Spring Cloud 的 RPC,如果替换成队列会有什么影响吗?不需要高性能的场景下可以互相替换吗?

本人了解甚少,上面都是班门弄斧的瞎说,如有不对,希望大神能指教一二。

16120 次点击
所在节点    程序员
129 条回复
shawndev
2019-07-04 18:27:34 +08:00
rpc 是通信手段,队列是数据结构。出现这种数据结构是因为内容可能会并发,堆积。所以我理解的两个东西不是一回事,不存在取代的关系。

猫能取代音乐吗?你要说能也算能。但我不会这么说。
springmarker
2019-07-04 18:31:02 +08:00
@shawndev #1 两者可能并没有明显的界限,RPC 同样可以用队列实现,这个帖子也不是对 “队列和 RPC 之前的区别”的讨论,而是在微服务中,两者用哪种更好一些。
xmge
2019-07-04 18:31:38 +08:00
@shawndev 感觉楼主的意思是:通过猫去接近一个姑娘,还是通过音乐。 可能通过猫更好一点吧
ikaros
2019-07-04 18:33:43 +08:00
1 楼结帖
Kaiv2
2019-07-04 18:34:39 +08:00
消息队列用来做异步处理,RPC 做同步处理。我的项目都是这样做的
sin30
2019-07-04 18:36:38 +08:00
我理解强依赖的调用关系,肯定是要走 RPC,并且明确获得返回结果的情况下才能继续的。
那些弱依赖的,类似只是通知一下其他服务做动作的,可以做成队列异步执行的,确保最终一致就行。
但是这个界限还是比较模糊的,理论上是可以把所有对外的调用都做成队列消息,异步让其他服务处理,不过这样的话设计起来就会复杂很多,你得定义多少消息类型,异步任务啊。
Aruforce
2019-07-04 18:38:04 +08:00
估计说的队列指的是具有 MQ 这类功能的东西吧;
需要返回结果的时候....用队列的还要将调用方线程阻塞掉使异步变同步,调用方线程不还是阻塞着么?那调用方线程直接 RPC 不行么?还用加个队列?这不是脱裤子放屁么....
springmarker
2019-07-04 18:39:08 +08:00
@ikaros #4 标题可能说的没那么明确,我再说清楚一点吧,我的意思是:现在 RPC 基本上都是“ client 直接连接 server (可能有个注册中心)”的模式,我说的 RPC 也指代这种 RPC。在使用这种 RPC 的业务中,同样可以用队列来实现,而且有些队列的优点是 RPC 无法取代的。
51300520
2019-07-04 18:39:50 +08:00
同步的用 rpc,异步的用队列,特别是量大要缓冲或者时间久那种,像发邮件。rpc 现在一般是用 etcd 或者 consul 这种来服务注册来实现类似 zookeeper 的功能
keepeye
2019-07-04 18:42:23 +08:00
微服务跟队列有冲突吗?压根不是一个概念啊老兄
keepeye
2019-07-04 18:43:19 +08:00
rpc 是微服务之间通信方式 队列是异步处理耗时任务的方式
springmarker
2019-07-04 18:46:09 +08:00
@sin30 #6 RPC 在网络层面也是异步,都得靠程序来保证同步异步。

@Aruforce #7 RPC 也是阻塞啊,我也没有说队列性能高啊。

@keepeye #11 我觉得不冲突,RPC 在网络层面也是异步,同样是靠程序保证同步。
monsterxx03
2019-07-04 18:56:46 +08:00
我的理解你是想用 rabbitmq 之类的 队列 broker 来实现类似 rpc 的同步调用方式?
chmaple
2019-07-04 19:00:21 +08:00
我一点点来说
第一点,丢失的概率,消息是会丢的、会失败的、可能要回滚的,RPC 立即返回结果或者使用 netty 之类的 NIO 框架管理 channel 返回结果,在这个角度上是 RPC 优于队列的,队列最大的好处是可以积压,但是最大的坏处就是本质是异步无法直接知道结果。
第二点,负载均衡,Nginx 是用来做什么的,要负载为什么不让专业的来而要自己来靠队列来实现均衡?
第三点,nginx 完美解决你的问题,发送端和接收端只要对接 nginx 就可以了

如果让我选择服务间通讯,我毫不犹豫会选 RPC 框架,实现简单、同步结果,项目简单的话我干脆面向 socket 编程,越粗暴越简单越好,再上一层就 NIO,多节点就上 nginx。
多了队列,就要维护队列、路由、TOPIC,要多一个 MQ 的监控和运维,要多考虑异步失败处理,要多个队列 listener 线程池和一堆相关的事情。
springmarker
2019-07-04 19:12:18 +08:00
@chmaple #14
1.netty 之类的返回数据也是异步,同样还是得靠 RPC 内部来控制同步,你要返回数据,使用双向队列 /两条队列同样不是不可能。
2.关于负载均衡,传统 RPC 和 Nginx 都是主动向 Server 端发送数据,这两者都无法或者很难判断 Server 端是否繁忙,如果由 Server 端主动判断自己是否空闲并获取消息不是更简单吗。

你说的简单粗暴是因为 RPC 封装好了网络和异步转同步细节,如果有成熟度和传统 RPC 差不多的由队列实现的 RPC,效果不是一样吗?
xuanbg
2019-07-04 19:15:22 +08:00
除非是错误信息能够返回前端的,否则都用队列传递数据而非 RPC。
henry19890701
2019-07-04 19:34:16 +08:00
@chmaple 同步调用,一样会出现类似“丢失的”,你远程 rpc 调用,报了了网络层超时,你咋知道对放接口是操作了,还是没操作

本质上,这两是两种编程模型:同步,异步。看你场景,哪个组织代码的逻辑比较顺畅,就用哪个,当然,绝大部分,还是同步的模型好理解
springmarker
2019-07-04 19:39:44 +08:00
@henry19890701 #17 我觉的本质上,无论 RPC 和队列,都是异步的,只不过 RPC 在异步的基础上提供了同步的功能,理论上队列同样可以封装一下改为同步。
justRua
2019-07-04 19:41:21 +08:00
你是想把 MQ 当做请求的分发器,等于所有请求都先到了 MQ,然后再给服务端消费。以前公司做 ETL 时有个类似的场景,数据抽取转换后先扔到 kafka,每个入库的程序去 kafka 拉取数据存数据库。这种需要数据不丢失的场景下挺合适的,大多业务场景的请求当服务器响应不过来了就丢弃了,把请求持久化保存起来也没用。
springmarker
2019-07-04 19:49:02 +08:00
@justRua #19 为什么要丢弃呢?既然用了微服务,只要不设置超时,这个请求不就是一直有用吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/580080

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX