RPC与其他通信技术的区别,以及RPC的底层原理
1、什么是 RPC?
远程过程调用(RPC) 是一种协议,它允许程序在不同计算机之间进行通信,让开发者可以像调用本地函数一样发起远程请求。
通过 RPC,开发者无需关注底层网络细节,能够更专注于业务逻辑的实现。
在传统的网络编程中,开发者需要手动处理多个繁琐的步骤,例如建立网络连接、序列化参数、发送请求数据、等待响应、反序列化数据以及处理错误等。
而通过 RPC,这些步骤都被自动化和抽象化了。
RPC 框架会自动处理这些底层的细节,开发人员只需像调用本地函数一样调用远程服务。
2、RPC 与 HTTP 的区别
随着互联网的发展,HTTP(超文本传输协议) 成为了数据传输的标准协议。
然而,选择 RPC 而非直接使用 HTTP 进行远程调用有其独特的理由。
• 面向过程 vs. 面向资源:HTTP 是一种面向资源的协议,强调通过 URL 访问和操作特定资源。
而 RPC 是面向过程的,允许开发者直接调用具体的函数或方法,更加自然和直观,特别是在需要执行复杂的业务逻辑时。
• 简化的调用体验:在传统的 HTTP 调用中,开发者需要手动构建请求,包括设置请求头、序列化参数、处理响应等。
而使用 RPC,所有这些复杂的底层工作都由 RPC 框架自动处理,大大简化了开发过程并降低了出错的可能性。
• 性能优势:虽然 HTTP 是一种文本协议,但在性能方面,RPC 通常更具优势。
RPC 框架常常使用高效的二进制格式进行数据传输,显著降低了数据体积和传输时间,特别适合于需要频繁调用和高性能的应用场景。
• 统一的接口调用:RPC 使得远程调用的过程与本地调用几乎相同,开发人员只需知道远程服务的接口定义,并不需要关心远程服务的具体实现或网络传输的细节。
3、RPC 的实战应用场景
计算资源的分布
假设你有一个复杂的计算任务,比如对大量数据进行分析或处理,而你的本地机器计算资源有限。
这时,你可以通过 RPC 调用远程服务器上的高性能计算资源。
示例场景:矩阵乘法
假设你需要对两个巨大的矩阵进行乘法运算,而你的本地机器性能有限。
你可以调用远程的高性能服务器来完成这个计算任务。
代码示例
// 本地调用(伪代码)
int main() {// 创建远程服务代理对象RemoteServiceProxy proxy("http://remote-server.com");// 调用远程服务的矩阵乘法函数Matrix result = proxy.matrix_multiply(matrix_a, matrix_b);// 输出结果std::cout << "Matrix multiplication result:" << result << std::endl;return 0;
}
注解
- 创建代理对象:通过 RemoteServiceProxy 创建一个代理对象,指定远程服务的地址。
- 调用远程函数:通过代理对象调用远程服务的 matrix_multiply 函数,就像调用本地函数一样。
- 输出结果:获取远程服务返回的结果并输出。
分布式系统中的服务调用
在现代微服务架构中,系统通常由多个服务组成,每个服务负责不同的功能。
通过 RPC,服务之间可以相互调用,以完成整个业务流程。
示例场景:电商系统中的订单处理
假设你在开发一个电商平台,订单处理涉及多个步骤,比如验证库存、处理支付、生成发票、通知物流等。
这些功能分别由不同的微服务来完成,它们可能运行在不同的服务器上。
通过 RPC,订单服务可以调用其他服务来完成整个订单处理流程。
代码示例
// 本地代码
void process_order(const Order& order) {// 通过RPC调用库存服务InventoryServiceProxy inventory_proxy("http://inventory-service.com");inventory_proxy.check_inventory(order.order_id);// 通过RPC调用支付服务PaymentServiceProxy payment_proxy("http://payment-service.com");payment_proxy.process_payment(order.order_id);// 通过RPC调用发票服务InvoiceServiceProxy invoice_proxy("http://invoice-service.com");invoice_proxy.generate_invoice(order.order_id);// 通过RPC通知物流LogisticsServiceProxy logistics_proxy("http://logistics-service.com");logistics_proxy.notify_logistics(order.order_id);
}
注解
- 创建服务代理:为每个微服务创建一个代理对象,指定服务的地址。
- 调用服务:通过代理对象调用各个服务的接口,完成订单处理的各个步骤。
- 流程控制:通过代码逻辑控制各个服务的调用顺序,确保业务流程的正确性。
4、什么时候使用 HTTP,什么时候使用 RPC?
场景对比
5、RPC 的工作原理
RPC 的工作流程可以分为以下几个关键步骤:
1、客户端调用本地代理(Stub)函数:客户端程序调用一个本地的函数(即代理函数,或称为 Stub),但这个函数并没有直接执行实际逻辑,而是充当一个“中介”。
2、序列化:代理函数将客户端的调用请求(包括函数名、参数等)打包成一个消息。
这个过程叫做序列化(或编组,Marshalling),即将数据转换为可以通过网络传输的格式。
3、发送请求到远程服务器:封装好的消息通过网络传输到远程服务器。
底层传输协议通常是 TCP、HTTP 或其他协议。
现代的 RPC 框架(如 gRPC)可能会使用 HTTP/2 协议来进行通信。
4、服务器接收请求并解包:服务器端接收到请求消息后,首先会将其解包(即反序列化,Unmarshalling),恢复出客户端调用的原始数据(如函数名、参数等)。
5、调用远程过程:服务器的代理函数将解包后的数据传递给实际的业务逻辑函数,服务器执行该函数并生成结果(或异常)。
6、封装响应并返回给客户端:执行完远程过程后,服务器将结果打包(序列化)成消息,并通过网络返回给客户端。
7、客户端接收响应并解包:客户端接收到服务器返回的响应消息后,再次解包(反序列化),恢复出远程过程的返回值。
最后,客户端的代理函数将结果返回给调用者,整个远程调用过程结束。
6、流行的 RPC 框架
gRPC
• 简介:gRPC 是由 Google 开发的高性能、开源的 RPC 框架,基于 HTTP/2 协议,支持多种编程语言。
• 特点:
• 高效的二进制序列化:使用 Protocol Buffers(protobuf)作为接口定义语言,提供高效的序列化和反序列化。
• 流式传输:支持单向和双向流式传输,适合需要实时数据传输的应用场景。
• 负载均衡和故障恢复:内置支持负载均衡、重试和故障恢复机制。
• 适用场景:适合微服务架构、高性能要求的分布式系统、需要跨语言支持的应用。
Apache Thrift
• 简介:Apache Thrift 是一个开源的跨语言服务开发框架,最初由 Facebook 开发,支持多种传输协议和数据格式。
• 特点:
• 多语言支持:支持多种编程语言,包括 Java、C++、Python、Ruby 等。
• 灵活的传输协议:可以选择不同的传输协议(如 TCP、HTTP)和数据格式(如 JSON、Binary)。
• 服务定义:使用 Thrift IDL(接口定义语言)来定义服务和数据结构。
• 适用场景:适合需要跨语言服务调用的应用,尤其是在多种技术栈共存的环境中。
JSON-RPC
• 简介:JSON-RPC 是一种轻量级的远程过程调用协议,使用 JSON 作为数据格式,简单易用。
• 特点:
• 简单易懂:协议简单,易于实现和调试,适合快速开发。
• 无状态:每个请求都是独立的,不需要维护会话状态。
• 广泛支持:几乎所有编程语言都支持 JSON,易于集成。
• 适用场景:适合小型项目、快速原型开发和需要简单通信的场景。
XML-RPC
• 简介:XML-RPC 是一种基于 XML 的远程过程调用协议,允许程序通过 HTTP 进行通信。
• 特点:
• 基于 XML:使用 XML 作为数据格式,适合需要与现有 XML 系统集成的场景。
• 简单的调用方式:通过 HTTP POST 请求发送 XML 数据,易于实现。
• 适用场景:适合需要与 XML 系统集成的应用,或在需要简单的远程调用时使用。
7、总结
选择合适的 RPC 框架和库取决于具体的应用需求、团队的技术栈以及性能要求。
gRPC 和 Apache Thrift 更适合高性能和复杂的分布式系统,而 JSON-RPC 和 XML-RPC 则适合简单的应用场景。
RPC 技术在分布式系统中发挥着重要作用,它简化了开发流程,提高了开发效率,同时也为高性能和低延迟的应用提供了支持。
相关文章:
RPC与其他通信技术的区别,以及RPC的底层原理
1、什么是 RPC? 远程过程调用(RPC) 是一种协议,它允许程序在不同计算机之间进行通信,让开发者可以像调用本地函数一样发起远程请求。 通过 RPC,开发者无需关注底层网络细节,能够更专注于业务逻…...
汽车售后ODX 和 OTX 详细分析
在汽车售后诊断领域,ODX 和 OTX 都是重要的标准,但它们的应用场景和特点有所不同,难以简单地评判哪个是绝对的主流。以下是对它们的详细分析。 ODX(Open Diagnostic data eXchange) 概述:ODX 是由 ASAM 制…...
深度学习天崩开局
李沐大神的d2l包导入, 这玩意需要python311版本,我现在版本已经313了,作为一个天生要强的男人,我是坚决不向低版本低头的。 然后我就研究啊,各种翻资料啊,然后deepseek加豆包都翻烂了, 最终所…...
面试算法高频04-分治与回溯
分治与回溯 分治和回溯算法,包括其概念、特性、代码模板,并结合具体题目进行讲解,旨在帮助学员理解和掌握这两种算法的应用。 分治与回溯的概念 分治(Divide & Conquer):本质上基于递归,先…...
整数编码 - 华为OD统一考试(A卷、C++)
题目描述 实现一种整数编码方法,使得待编码的数字越小,编码后所占用的字节数越小。 编码规则如下: 编码时7位一组,每个字节的低7位用于存储待编码数字的补码。字节的最高位表示后续是否还有字节,置1表示后面还有更多的字节&…...
对访问者模式的理解
对访问者模式的理解 一、场景二、不采用访问者模式1、代码2、特点 三、采用访问者模式1、代码2、特点 四、思考 一、场景 我们有一个图形系统,系统中有多种图形对象(如圆形、方形等),每种图形对象都有不同的属性和行为。现在需要对…...
第三次PID状态机
以下是 apply_params 函数的实现步骤和代码示例: 1. 定义参数结构体 在头文件中定义 PID_Params 结构体,包含需要动态调整的 PID 参数: // ms_hal_photo_sensor.h typedef struct {float Kp; // 比例系数float Ki; // …...
如何在大型项目中有效使用TypeScript进行类型定义?
嗨,大家好,我是莫循,Typescript是JavaScript的超集,现在已经广泛用于前端开发,那么在项目中如何用好类型定义呢?以下是一些可以提供参考的案例实践。 一、类型组织策略 1. 模块化类型定义 按功能/模块划分…...
C4D XP 粒子动画云端渲染指南
在 C4D 动画制作领域,XP 粒子特效因其复杂的动力学计算常成为渲染瓶颈。传统本地渲染不仅耗时漫长,还需持续占用高配置硬件。而借助专业云渲染平台,创作者可突破物理限制,高效完成 XP 粒子动画的最终输出。 以渲染 101 平台为例&a…...
mysql知识总结 基础篇
Mysql知识总结 1. 执行一条sql语句 期间发生了什么?1. 如何查看mysql服务被多少个客户端链接了2. 空闲链接会一直闲置嘛?3. mysql的链接数量有限制嘛?4. 我们如何知道mysql要使用哪个索引5. 什么是覆盖索引 2. MySQL 一行记录是怎么存储的&am…...
基于条码数据生成校验密码的C++实现方案
前言 在医疗试剂、工业产品等需要严格追踪管理的领域,条码系统常被用于标识产品信息。本文将详细介绍4种用C实现的条码密码生成算法,这些算法可以根据条码前11位数据生成2位校验密码(第9、10位),用于数据校验或简单防…...
前端工具方法整理
文章目录 1.在数组中找到匹配项,然后创建新对象2.对象转JSON字符串3.JSON字符串转JSON对象4.有个响应式对象,然后想清空所有属性5.判断参数不为空6.格式化字符串7.解析数组内容用逗号拼接 1.在数组中找到匹配项,然后创建新对象 const modifi…...
[数据结构]图krusakl算法实现
目录 Kruskal算法 Kruskal算法 我们要在连通图中去找生成树 连通图:在无向图中,若从顶点v1到顶点v2有路径,则称顶点v1与顶点v2是连通的。如果图中任意一对顶点都是连通的,则称此图为连通图。 生成树:一个连通图的最小…...
18-产品经理-跟踪进度
禅道是一个可以帮助产品经理跟踪研发进度的系统。通过禅道,产品经理可以从多个角度了解产品的研发状态。在仪表盘中,可以展示所有产品或单一产品的概况,包括需求、计划和发布数量,研发需求状态,Bug修复率和计划发布数。…...
华为机试—挑7
题目 你需要统计 1 到 n 之间与 7 有关的数字的个数。 与 7 有关的数字包括: 是 7 的倍数(如 7,14,21 等);包含数字 7(如 17,27,37,⋯ ,70,71,72,⋯等)。 示例 输入:20 输出:3 说…...
【区块链安全 | 第三十四篇】合约审计之重入漏洞
文章目录 概念漏洞代码代码审计攻击代码攻击过程总结示例修复建议审计思路 概念 以太坊的智能合约可以互相调用,也就是说,一个合约可以调用另一个合约的函数。除了外部账户,合约本身也可以持有以太币并进行转账。当合约接收到以太币时&#…...
Java虚拟机——JVM(Java Virtual Machine)解析一
1.JVM是什么? 1.1 JVM概念 Java Virtual Machine (JVM) 是JDK的核心组件之一,它使得 Java 程序能够在任何支持 JVM 的设备或操作系统上运行,而无需修改源代码 JDK是什么,JDK和JVM是什么关系?1.Java IDE(Integrated …...
【JVM】question
问题 JVM线程是用户态还是内核态 java线程在jdk1.2之前,是基于名为“绿色线程”的用户线程实现的,这导致绿色线程只能同主线程共享CPU分片,从而无法利用多核CPU的优势。 由于绿色线程和原生线程比起来在使用时有一些限制, jdk1.2…...
页面编辑器CodeMirror初始化不显示行号或文本内容
延迟刷新 本来想延迟100毫秒的,但是会出现样式向左偏移的情况,于是试了试500毫秒,发现就没有问题了,可能是样式什么是需要一个加载过程吧。 useEffect(() > {editorRef.current?.setValue(value || );setTimeout(() > {edi…...
顺序表——C语言实现
目录 一、线性表 二、顺序表 1.实现动态顺序表 SeqList.h SeqList.c Test.c 问题 经验:free 出问题,2种可能性 解决问题 (2)尾删 (3)头插,头删 (4)在 pos 位…...
OpenCV 图形API(21)逐像素操作
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在OpenCV的G-API模块中,逐像素操作指的是对图像中的每个像素单独进行处理的操作。这些操作可以通过G-API的计算图(Graph …...
车载联网终端4G汽车TBOX介绍定义与概述
汽车 TBOX(Telematics Box)是专为汽车设计的远程通信终端设备,属于车联网系统的关键组成部分。车联网系统一般包含主机、汽车 T - BOX、手机 APP 及后台系统。融合了车身网络和 4G 无线通信技术,为汽车提供丰富的 Telematics 服务…...
CentOS无法安装Vim文本编辑器问题以及解决方法
1.问题一:用户权限不够 解决方法一:切换到root用户 解决方法二:给本用户添加权限 2.问题二:镜像源问题:官方镜像源可能已经失效 解决方法: 1. 检查网络连接 2. 检查和配置 DNS 3. 更换镜像源&#…...
Kettle如何与应用集成
Kettle(Pentaho Data Integration,PDI)可以通过多种方式与应用程序集成,以下是7种主流方法及具体实现示例: 一、命令行调用(最基础) # 执行转换(Transformation) ./pan.…...
Pytorch torch.nn.utils.rnn.pad_sequence 介绍
torch.nn.utils.rnn.pad_sequence 是 PyTorch 中一个用于填充序列的实用函数,它主要用于处理长度不一的序列数据,将这些序列填充到相同的长度,以便能将它们组合成一个批量(batch)输入到神经网络中。以下是详细介绍&…...
4.7正则表达式
1.字符匹配 一般字符匹配自身. 匹配任意字符(换行符\n除外),一个点占一位\转义字符,使其后一个字符改变原来的意思(\.就是.)[......]字符集,对应的位置可以是字符集中的任意字符.字符集中的字符可以逐个列出,也可以给出范围如[abc]或[a-c] [^abc] 表示取反…...
CogPatInspectTool工具
CogPatInspectTool是康耐视中的一种模板比对的视觉检测工具,主要用于产品不良检测。其核心功能是通过将输入图像与预先训练好的模板进行对比,识别出两者之间的差异,并生成高亮差异图,从而判断产品是否存在缺陷。 效果图 CogPatIn…...
牛客周赛 + 洛谷刷题
秘藏 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N 200010; ll a[N], b[N]; int n, k; ll dp[2][N];//dp[i][j]是在i界中取了j之前的最大值 int main(){ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);cin >> n >&…...
【数据结构】图论存储革新:十字链表双链设计高效解决有向图入度查询难题
十字链表 导读一、邻接表的优缺点二、十字链表2.1 结点结构2.2 原理解释2.2.1 顶点表2.2.2 边结点2.2.3 十字链表 三、存储结构四、算法评价4.1 时间复杂度4.2 空间复杂度 五、优势与劣势5.1 优势5.2 劣势5.3 特点 结语 导读 大家好,很高兴又和大家见面啦ÿ…...
【JavaScript】十五、事件对象与环境对象
文章目录 1、事件对象1.1 获取事件对象1.2 常用属性1.3 案例:回车发布评论 2、环境对象this3、回调函数4、案例:tab切换5、案例:全选文本框📖 1、事件对象 事件对象: 也是个对象,object,里面存…...
OJ--第N个泰波那契数列
1137. 第 N 个泰波那契数 - 力扣(LeetCode) 1 题干部分 2 拆解 1 状态表示:dp[i] 2 状态转移方程:dp[i]dp[i-1]dp[i-2]dp[i-3] 3 初始化:让dp[0]0,dp[1]dp[2]1 4 填表顺序:从dp[3]开始填从左往右填 5 返回值:dp[n]即为返回的…...
Python从入门到高手8.1节-元组类型详解
目录 8.1.1 理解元组类型 8.1.2 元组的类型名 8.1.3 元组的定义 8.1.4 元组的解包 8.1.5 元组是可迭代的 8.1.6 假期就这么结束了 8.1.1 理解元组类型 元组与列表有着相同的数据结构,区别在于,元组是不可变的数据类型,而列表是可变的数…...
使用 Qt 和 OBS 工具检测系统硬件编码器支持情况(NVENC、QSV、AMF)
在开发涉及视频处理的软件时,判断系统是否支持硬件加速编码器(如 NVIDIA NVENC、Intel QSV、AMD AMF)对于性能优化至关重要。本文将介绍如何结合 Qt 与 OBS Studio 附带的小工具程序,实现一个完整、异步且不会卡住 UI 的硬件加速检测模块。 一、背景与目标 硬件加速编码器…...
Python爬虫生成CSV文件的完整流程
引言 在当今数据驱动的时代,网络爬虫已成为获取互联网数据的重要工具。Python凭借其丰富的库生态系统和简洁的语法,成为了爬虫开发的首选语言。本文将详细介绍使用Python爬虫从网页抓取数据并生成CSV文件的完整流程,包括环境准备、网页请求、…...
图论:多源最短路
多源最短路 B3647 【模板】Floyd - 洛谷 #include<iostream> #include<cstring> using namespace std;const int N 110; int f[N][N]; int n, m;int main() {memset(f, 0x3f, sizeof(f));//对于重边的处理取较小值,所以要把全部都初始化成无穷大&…...
2024年已备案大模型发展趋势分析
2024年已备案大模型发展趋势分析 随着生成式人工智能技术的快速发展,其在各个领域的应用逐渐深入。为了规范和促进生成式人工智能服务的健康发展,国家互联网信息办公室发布了《生成式人工智能服务已备案信息》。本文将基于已备案信息,分析生成式人工智能服务的发展趋势,并…...
spring功能汇总
1.创建一个dao接口,实现类;service接口,实现类并且service里用new创建对象方式调用dao的方法 2.使用spring分别获取dao和service对象(IOC) 注意 2中的service里面获取dao的对象方式不用new的(DI) 运行测试: 使用1的方式创建servic…...
Transformer - Feed Forward前馈网络
一、数学原理 1. 前馈神经网络公式 2. Dropout公式 二、代码实现 import math import torchimport torch.nn as nnclass FeedForward(nn.Module):def __init__(self, d_model, dff, dropout):super().__init__()self.W1 nn.Linear(d_model, dff)self.W2 nn.Linear(dff, d_mo…...
Compose Multiplatform+Kotlin Multiplatfrom 第五弹跨平台 截图
截图功能 Compose MultiplatformKotlin Multiplatfrom下实现桌面端的截图功能,起码搞了两星期,最后终于做出来了,操作都很流畅,截取的文件大小也正常,可参考支持讨论! 功能效果 代码实现 //在jvmMain下创…...
算法题(119):高精度减法
审题: 本题高精度减法主要是要区分正负号,然后进行模拟 思路: 方法一:模拟法 首先本题需要我们利用字符串进行大数相减 第一步:区分s1和s2谁更大 先从数的位数进行判断,然后再从高到低的位数进行判断 第二步…...
使用成员函数指针数组简化C++类中的操作
使用成员函数指针数组简化C类中的操作 在C编程中,我们常常会遇到需要对一组相似的操作进行处理的情况。例如,在一个游戏引擎中,你可能希望角色能够执行一系列的动作,如行走、跳跃或攻击等。为了简化这些操作的管理和调用…...
WebGL数学手记:矩阵基础
一、矩阵的定义 矩阵,数学术语。在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合。 1.英文发音(Matrix) Matrix的发音类似于中文的[美吹克斯],知道它的发音。方便后期看教程时…...
Python爬取数据(二)
一.example2包下的 1.re模块的compile函数使用 import repatternre.compile(r\d) print(pattern) 2.match的方法使用 import re patternre.compile(r\d) # m1pattern.match(one123twothree345four) #参数2:指定起始位置(包含),参数3:终止位置(包含),…...
我的NISP二级之路-01
目录 一.SSE-CMM系统安全工程-能力成熟度模型(Systems Security Engineering - Capability Maturity Model) 二.ISMS 即信息安全管理体系(Information Security Management System),是一种基于风险管理的、系统化的管理体系 三.Kerberos协议 1. 用户登录与 AS 请求 2…...
自制简易 Shell:像搭建积木小屋一样打造命令交互小天地
目录 准备工作:搭建小屋的材料 打造小屋的 “身份牌” 接收指令:小屋的 “对讲机” 拆解指令:把大任务拆成小积木 执行指令:小屋的 “行动队” 特殊指令:小屋的 “特色功能” 小屋的日常运转 完整代码 啥是 …...
WEB安全--内网渗透--利用Net-NTLMv2 Hash
一、前言 在前两篇文章中分析了NTLM协议中Net-NTLMv2 Hash的生成、如何捕获Net-NTLMv2 Hash,现在就来探讨一下在内网环境中,如何利用Net-NTLMv2 Hash进行渗透。 二、Net-NTLM Hash的破解 工具:hashcat 原理:利用其内部的字典对…...
MySQL 数据库操作指南:从数据库创建到数据操作
关键词:MySQL;数据库操作;DDL;DML 一、引言 MySQL 作为广泛应用的关系型数据库管理系统,对于开发人员和数据库管理员而言,熟练掌握其操作至关重要。本文章通过一系列 SQL 示例,详细阐述 MySQL…...
从传递函数到PID控制器
在过程控制中,按偏差的比例(P,Proportional)、积分(I,Integral)和微分(D,Differential)进行控制的PID控制器(亦称PID调节器)是应用最为…...
抓wifi无线空口包之Ubuntu抓包(二)
一、设置网卡信道和频段,并抓包 1、使用iwconfig查看自己机器的无线网卡名称 wangwang-ThinkCentre-M930t-N000:~$ iwconfig lo no wireless extensions. eno1 no wireless extensions. enxc8a3624ab329 no wireless extensions. wlx90de80d1b5b1 IE…...
使用protobuf编译提示无法打开包括文件: ‘absl/log/absl_log.h’: No such file or directory
问题原因 Protobuf 依赖 Abseil: Protobuf 3.20 版本开始依赖 Abseil,但你的系统未正确安装或配置 Abseil。 头文件路径未包含: 编译器找不到 absl/log/absl_log.h,可能是因为 Abseil 未正确安装或未在项目中设置包含路径。 …...