答疑 | 基础篇与进阶篇思考题答案合集

简介: 本文围绕RPC核心机制展开,涵盖请求响应关联(消息ID)、动态代理替代方案(Service存根)、流式传输优势(InputStream减少拷贝)、流量切换(权重、分组)、异常重试时机(负载均衡前)、服务重启策略、熔断限流降级等实践问题,并探讨开发测试环境隔离方案,助力构建高效稳定的分布式系统。(239字)

第 2 讲 思考题:在 RPC 里面,我们是怎么实现请求跟响应关联的?

首先我们要弄清楚为什么要把请求与响应关联。这是因为在 RPC 调用过程中,调用端会向服务端发送请求消息,之后它还会收到服务端发送回来的响应消息,但这两个操作并不是同步进行的。在高并发的情况下,调用端可能会在某一时刻向服务端连续发送很多条消息之后,才会陆续收到服务端发送回来的各个响应消息,这时调用端需要一种手段来区分这些响应消息分别对应的是之前的哪条请求消息,所以我们说 RPC 在发送消息时要请求跟响应关联。

解决这个问题不难,只要调用端在收到响应消息之后,从响应消息中读取到一个标识,告诉调用端,这是哪条请求消息的响应消息就可以了。在这一讲中,你会发现我们设计的私有协议都会有消息 ID,这个消息 ID 的作用就是起到请求跟响应关联的作用。调用端为每一个消息生成一个唯一的消息 ID,它收到服务端发送回来的响应消息如果是同一消息 ID,那么调用端就可以认为,这条响应消息是之前那条请求消息的响应消息。


第 5 讲 思考题:如果没有动态代理帮我们完成方法调用拦截,用户该怎么完成 RPC 调用?

这个问题我们可以参考下 gRPC 框架。gRPC 框架中就没有使用动态代理,它是通过代码生成的方式生成 Service 存根,当然这个 Service 存根起到的作用和 RPC 框架中的动态代理是一样的。

gRPC 框架用代码生成的 Service 存根 来代替动态代理主要是为了实现多语言的客户端,因为有些语言是不支持动态代理的,比如 C++、go 等,但缺点也是显而易见的。如果你使用过 gRPC,你会发现这种代码生成 Service 存根的方式与动态代理相比还是很麻烦的,并不如动态代理的方式使用起来方便、透明。


第 6 讲 思考题:在 gRPC 调用的时候,我们有一个关键步骤就是把对象转成可传输的二进制,但是在 gRPC 里面,我们并没有直接转成二进制数组,而是返回一个 InputStream,你知道这样做的好处是什么吗?

RPC 调用在底层传输过程中也是需要使用 Stream 的,直接返回一个 InputStream 而不是二进制数组,可以避免数据的拷贝。


第 8 讲 思考题:目前服务提供者上线后会自动注册到注册中心,服务调用方会自动感知到新增的实例,并且流量会很快打到该新增的实例。如果我想把某些服务提供者实例的流量切走,除了下线实例,你有没有想到其它更便捷的办法呢?

解决这个问题的方法还是有很多的,比如留言中提到的改变服务提供者实例的权重,将权重调整为 0,或者通过路由的方式也可以。

但解决这个问题最便捷的方式还是使用动态分组,在 第 16 讲 中我讲解了业务分组的概念,通过业务分组来实现流量隔离。如果业务分组是动态的,我们就可以在管理平台动态地自由调整,那是不是就可以实现动态地流量切换了呢?这个问题我们还会在高级篇中详解,期待一下。


第 12 讲 思考题:在整个 RPC 调用的流程中,异常重试发生在哪个环节?

在回答这个问题之前,我们先回想下这一讲中讲过的内容。我在讲 RPC 为什么需要异常重试时我说过,如果在发出请求时恰好网络出现问题了,导致我们的请求失败,我们可能需要进行异常重试。从这一点我们可以看出,异常重试的操作是要在调用端进行的。因为如果在调用端发出请求时恰好网络出现问题导致请求失败,那么这个请求很可能还没到达服务端,服务端当然就没办法去处理重试了。

另外我还讲过,我们需要在所有发起重试、负载均衡选择节点的时候,去掉重试之前出现过问题的那个节点,以保证重试成功率。由此可见异常重试的操作应该发生在负载均衡之前,在发起重试的时候,会调用负载均衡插件来选择一个服务节点,在调用负载均衡插件时我们要告诉负载均衡需要刨除哪些有问题的服务节点。

在整个 RPC 调用的过程中,从动态代理到负载均衡之间还有一系列的操作,如果你研究过开源的 RPC 框架,你会发现在调用端发送请求消息之前还会经过过滤链,对请求消息进行层层的过滤处理,之后才会通过负载均衡选择服务节点,发送请求消息,而异常重试操作就发生在过滤链处理之后,调用负载均衡选择服务节点之前,这样的重试是可以减少很多重复操作的。


第 14 讲 思考题:在启动预热那部分,我们特意提到过一个问题,就是「当大批量重启服务提供方的时候,会导致请求大概率发到没有重启的机器上,这时服务提供方有可能扛不住」,不知道你是怎么看待这个问题的,是否有好的解决方案呢?

我们可以考虑在非流量高峰的时候重启服务,将影响降到最低;也可以考虑分批次重启,控制好每批重启的服务节点的数量,当一批服务节点的权重与访问量都到正常水平时,再去重启下一批服务节点。


第 15 讲 思考题:在使用 RPC 的过程中业务要实现自我保护,针对这个问题你是否还有其他的解决方案?

通过这一讲我们知道,在 RPC 调用中无论服务端还是调用端都需要自我保护,服务端自我保护的最简单有效的方式是「限流」,调用端则可以通过「熔断」机制来进行自我保护。

除了熔断和限流外,相信你一定听过「降级」这个词。简单来说就是当一个服务处理大量的请求达到一定压力的时候,我们可以让这个服务在处理请求时减少些非必要的功能,从而降低这个服务的压力。

还有就是我们可以通过服务治理,降低一个服务节点的权重来减轻某一方服务节点的请求压力,达到保护这个服务节点的目的。


第 16 讲 思考题:在我们的实际工作中,测试人员和开发人员的工作一般都是并行的,这就导致一个问题经常出现:开发人员在开发过程中可能需要启动自身的应用,而测试人员为了能验证功能,会在测试环境中部署同样的应用。如果开发人员和测试人员用的接口分组名刚好一样,在这种情况下,就可能会干扰其它正在联调的调用方进行功能验证,进而影响整体的工作效率。不知道面对这种情况,你有什么好办法吗?

我们可以考虑配置不同的注册中心,开发人员将自己的服务注册到注册中心 A 上,而测试人员可以将自己的服务注册到测试专属的注册中心 B 上,这样测试人员在验证功能的时候,调用端会从注册中心 B 上拉取服务节点,开发人员重启自己的服务是影响不到测试人员的。

如果你使用过或者了解 k8s 的话,你一定知道「命名空间」的概念,RPC 框架如果支持命名空间,也是可以解决这一问题的。

注意这个问题的背景,背景是只有一个注册中心,你的服务也注册上去了,并且和分组命名是一样的,只有这个前提下才会导致上述的问题发生

相关文章
|
1天前
|
数据采集 人工智能 安全
|
11天前
|
云安全 监控 安全
|
2天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
938 150
|
2天前
|
编解码 人工智能 机器人
通义万相2.6,模型使用指南
智能分镜 | 多镜头叙事 | 支持15秒视频生成 | 高品质声音生成 | 多人稳定对话
|
16天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1662 8
|
7天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
617 152
|
9天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
587 15
|
9天前
|
人工智能 自然语言处理 API
Next AI Draw.io:当AI遇见Draw.io图表绘制
Next AI Draw.io 是一款融合AI与图表绘制的开源工具,基于Next.js实现,支持自然语言生成架构图、流程图等专业图表。集成多款主流大模型,提供智能绘图、图像识别优化、版本管理等功能,部署简单,安全可控,助力技术文档与系统设计高效创作。
672 151