基于 Apache Commons Pool 实现的 gRPC 连接池管理类 GrpcChannelPool 性能分析与优化

基于 Apache Commons Pool 实现的 gRPC 连接池管理类 GrpcChannelPool 性能分析与优化

1. 输出关键信息的代码示例

日志记录方法

使用以下代码记录连接池的关键信息,帮助分析连接池的状态和性能瓶颈:

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public class GrpcChannelPoolAnalyzer {private static final Logger logger = LoggerFactory.getLogger(GrpcChannelPoolAnalyzer.class);private final GenericObjectPool<GrpcChannel> grpcChannelPool;public GrpcChannelPoolAnalyzer(GenericObjectPool<GrpcChannel> grpcChannelPool) {this.grpcChannelPool = grpcChannelPool;}public void logPoolStatus() {logger.info("=== GrpcChannelPool Status ===");logger.info("Num Active: {}", grpcChannelPool.getNumActive());logger.info("Num Idle: {}", grpcChannelPool.getNumIdle());logger.info("Num Waiters: {}", grpcChannelPool.getNumWaiters());logger.info("Total Borrowed Count: {}", grpcChannelPool.getBorrowedCount());logger.info("Total Created Count: {}", grpcChannelPool.getCreatedCount());logger.info("Total Returned Count: {}", grpcChannelPool.getReturnedCount());logger.info("Total Destroyed Count: {}", grpcChannelPool.getDestroyedCount());}
}

调用日志记录

public static void main(String[] args) {// 创建连接池GenericObjectPool<GrpcChannel> grpcChannelPool = new GenericObjectPool<>(new GrpcChannelFactory());// 初始化分析器GrpcChannelPoolAnalyzer analyzer = new GrpcChannelPoolAnalyzer(grpcChannelPool);// 定期输出日志analyzer.logPoolStatus();
}

2. 关键方法的含义和影响分析

A. getBorrowedCount()

  • 含义
    • 自池创建以来,成功借出的对象总数。
    • 表示连接池处理了多少次借用请求。
  • 可能的影响
    • 如果 getBorrowedCount 很高,说明连接池被频繁借用。这可能导致以下问题:
      1. 如果连接池配置的 maxTotal 过低,导致线程排队等待可用连接。
      2. 如果池中连接被频繁销毁或验证失败,导致额外的连接创建开销。
    • 借用连接时慢可能是由于等待连接归还或新建连接的时间过长。

B. getCreatedCount()

  • 含义
    • 自池创建以来,总共创建的对象数量。
    • 包括了所有当前活跃、空闲和已销毁的对象。
  • 可能的影响
    • 如果 getCreatedCount 很高,表明连接池频繁创建新连接,可能是因为:
      1. 空闲连接销毁过快:池中配置了较小的 maxIdle 或空闲对象检测频率较高,导致连接被频繁销毁。
      2. 验证失败:连接在借用时被标记为无效,从而需要创建新连接。
      3. 连接使用时间长:池内的连接未及时归还,导致新连接不断创建。
    • 借用连接时慢可能是由于新连接创建速度较慢(如涉及网络请求、SSL 加密等复杂逻辑)。

C. getNumActive()

  • 含义
    • 当前正在被使用的连接数。
  • 可能的影响
    • 如果 getNumActive 接近或等于 maxTotal
      1. 新的借用请求将被阻塞,等待有连接归还或新建。
      2. 借用延迟的时间取决于前一个连接释放的速度或新连接创建时间。

D. getNumIdle()

  • 含义
    • 当前池中空闲的连接数。
  • 可能的影响
    • 如果 getNumIdle 为 0,意味着没有可立即借用的连接。
    • 此时,借用请求会被阻塞,直到:
      1. 一个连接被归还。
      2. 一个新连接被创建。
    • 借用连接时慢通常与空闲连接耗尽直接相关。

E. getNumWaiters()

  • 含义
    • 当前等待借用连接的线程数。
  • 可能的影响
    • 如果等待线程数较多,表明连接池无法及时满足请求。
    • 这种情况可能因为 maxTotal 设置过低或连接释放速度过慢导致。

F. getDestroyedCount()

  • 含义
    • 自池创建以来,被销毁的连接总数。
  • 可能的影响
    • 如果销毁的连接数较高,可能导致借用连接时需要频繁创建新连接,从而增加延迟。
    • 检查空闲对象的检测配置是否合理(如 timeBetweenEvictionRunsMillisminEvictableIdleTimeMillis)。

3. 借用对象慢的分析原因

根据以上信息,以下是常见可能的原因及解决方案:

原因 1:空闲连接不足

  • 表现getNumIdle 为 0。
  • 分析:池中没有空闲连接供借用,新的借用请求需要等待归还或创建新连接。
  • 解决方案
    1. 增加 minIdlemaxIdle,确保有足够的空闲连接。
    2. 减少连接创建的开销(优化 makeObject() 方法)。

原因 2:线程等待超时

  • 表现getNumWaiters 高,getNumActive 接近或等于 maxTotal
  • 分析:借用请求太多,超过了池的最大容量。
  • 解决方案
    1. 增加 maxTotal,允许池处理更多并发连接。
    2. 优化业务逻辑,减少连接使用时间。

原因 3:连接频繁销毁和创建

  • 表现getCreatedCountgetDestroyedCount 较高。
  • 分析:可能因连接超时、验证失败或空闲销毁策略不合理导致。
  • 解决方案
    1. 调整连接池的空闲销毁参数(如 timeBetweenEvictionRunsMillisminEvictableIdleTimeMillis)。
    2. 优化连接验证逻辑,减少验证失败的情况。

原因 4:连接创建耗时

  • 表现getNumActive 达到 maxTotalgetNumIdle 为 0。
  • 分析:新连接的创建时间太长,可能因网络延迟、认证复杂或初始化慢。
  • 解决方案
    1. 优化连接的创建过程(减少网络调用、使用连接池化资源)。
    2. 预热池:配置 minIdle 和定期检测任务。

4. 日志输出与示例分析

假设运行时日志输出如下:

INFO - === GrpcChannelPool Status ===
INFO - Num Active: 10
INFO - Num Idle: 0
INFO - Num Waiters: 95
INFO - Total Borrowed Count: 500
INFO - Total Created Count: 520
INFO - Total Destroyed Count: 10

分析

  1. Num Idle = 0

    • 空闲连接不足,导致新的借用请求需要等待。
  2. Num Waiters = 95

    • 表示 95 个线程正在等待借用连接,系统压力较大。
  3. Total Created Count = 520,Total Destroyed Count = 10

    • 表明创建频率高,销毁频率低,可能是空闲检测频率较低或借用时触发新连接的创建逻辑。

解决方案

  • 增加 maxTotal(如 50)。
  • 设置合理的 minIdle(如 10)并启用预热机制。
  • 优化连接创建速度,减少延迟。

5. 如何获取 maxTotal 与其关系

获取 maxTotal 的方法

maxTotal 是连接池中可同时活跃对象的最大数量。在 Apache Commons Pool 中,通过 GenericObjectPoolConfig 设置并管理此参数。

获取 maxTotal 的代码

如果你有一个 GenericObjectPool 实例,可以通过以下代码获取 maxTotal 的值:

int maxTotal = grpcChannelPool.getMaxTotal();
System.out.println("Max Total: " + maxTotal);

maxTotalNumActive 的关系

定义
  • maxTotal:

    • 定义了连接池中允许同时活跃的最大对象数量。
    • 当活跃对象数量达到 maxTotal 时,新的借用请求会被阻塞,直到有对象归还或超时。
  • NumActive:

    • 表示当前池中被借用(活跃使用)的对象数量。
    • NumActive 的值始终小于或等于 maxTotal
关系描述
  1. NumActive ≤ maxTotal

    • NumActive 是当前实际使用的对象数量,受 maxTotal 的限制。
    • 如果 NumActive 达到 maxTotal,连接池不会再创建新对象,而是让新的请求进入等待状态。
  2. 连接池满的场景

    • NumActive == maxTotalNumIdle == 0 时,连接池满载,新的借用请求将进入等待队列,直到有对象被归还或超时。
  3. 调整 maxTotal 的影响

    • 增加 maxTotal:允许池支持更多并发请求,但需要足够的系统资源(如数据库连接数)。
    • 减少 maxTotal:限制池的最大并发能力,可能导致更多请求进入等待队列。

示例分析

代码示例

以下代码展示如何获取 maxTotal 和检查其与 NumActive 的关系:

import org.apache.commons.pool2.impl.GenericObjectPool;public class PoolStatusChecker {public static void logPoolStatus(GenericObjectPool<?> pool) {int maxTotal = pool.getMaxTotal();int numActive = pool.getNumActive();int numIdle = pool.getNumIdle();System.out.println("Max Total: " + maxTotal);System.out.println("Num Active: " + numActive);System.out.println("Num Idle: " + numIdle);if (numActive == maxTotal && numIdle == 0) {System.out.println("Connection pool is at full capacity.");}}
}
运行结果示例

假设运行时的池状态如下:

Max Total: 10
Num Active: 10
Num Idle: 0

分析

  • 当前活跃连接数 NumActive = 10 已经达到 maxTotal
  • 此时,如果有新的借用请求,将进入等待队列,可能导致延迟。

总结

  • maxTotal 定义了池中最大同时活跃对象的数量,而 NumActive 是当前实际使用的对象数量。
  • NumActive 始终小于或等于 maxTotal,当 NumActive == maxTotalNumIdle == 0 时,新的借用请求将进入等待状态。
  • 根据业务需求动态调整 maxTotal,并结合 NumActiveNumWaiters 的监控数据,优化连接池配置。

GrpcChannelPool 性能分析与数学关系

1. 关键值的意义和关系

活跃连接数 (NumActive)

  • 当前正在使用的连接数量。
  • NumActive ≤ maxTotal(活跃连接不能超过最大连接数)。

空闲连接数 (NumIdle)

  • 当前池中未被使用的连接数量。
  • NumIdle + NumActive ≤ maxTotal(空闲和活跃连接之和不能超过池中允许的最大连接数)。

等待线程数 (NumWaiters)

  • 当前等待借用连接的线程数。
  • NumActive == maxTotalNumIdle == 0 时,新的请求进入等待队列,此时 NumWaiters > 0

最大连接数 (maxTotal)

  • 池中允许的最大同时活跃连接数。
  • 限制了 NumActiveNumIdle 的上限。

2. 累积统计值

借用总数 (Total Borrowed Count)

  • 表示自池创建以来成功借出的对象总数。
  • Total Borrowed Count ≥ NumActive(历史借用次数必然大于或等于当前活跃数)。

创建总数 (Total Created Count)

  • 表示自池创建以来创建的对象总数。
  • Total Created Count ≥ NumActive + NumIdle(当前池中活跃和空闲连接数量必须由创建的连接数提供)。

归还总数 (Total Returned Count)

  • 表示自池创建以来归还的对象总数。
  • Total Returned Count = Total Borrowed Count - NumActive(归还的连接数等于借用总数减去当前未归还的活跃连接数)。

销毁总数 (Total Destroyed Count)

  • 表示自池创建以来销毁的对象总数。
  • Total Destroyed Count = Total Created Count - (NumActive + NumIdle)(销毁的连接数等于创建的连接数减去池中当前剩余的活跃和空闲连接)。

3. 主要数学运算关系

在这里插入图片描述


4. 示例分析

假设运行时池的状态如下:

  • maxTotal = 10
  • NumActive = 6
  • NumIdle = 2
  • NumWaiters = 3
  • Total Borrowed Count = 50
  • Total Created Count = 15
  • Total Returned Count = 44
  • Total Destroyed Count = 7

验证数学关系:

在这里插入图片描述


5. 如何利用这些关系分析性能问题

通过以上数学关系,可以监控和诊断连接池的问题。例如:

池容量不足

  • 表现
    • 如果 NumActive + NumIdle 长期接近或等于 maxTotal,且 NumWaiters > 0
  • 原因
    • 连接池容量不足,导致大量线程排队。
  • 解决方案
    • 增加 maxTotal

连接泄漏

  • 表现
    • 如果 Total Borrowed Count - Total Returned Count ≠ NumActive
  • 原因
    • 存在未归还的连接。
  • 解决方案
    • 检查业务代码,确保每次借用的连接都正确归还。

连接频繁创建销毁

  • 表现
    • 如果 Total Destroyed Count 很高。
  • 原因
    • 连接被频繁销毁,可能是因为空闲策略不合理。
  • 解决方案
    • 调整 minIdle 和空闲销毁参数。

6. 总结

这些值之间的数学关系提供了诊断连接池运行状态的重要依据。通过监控和分析这些关系,可以:

  • 优化连接池的配置(如 maxTotalminIdle 等)。
  • 发现性能瓶颈(如等待时间过长、连接不足等)。
  • 及时修复问题(如连接泄漏或资源浪费)。

GrpcChannelPool 预热机制详解

1. 预热机制的概念

预热机制是指在连接池启动时或者空闲连接不足时,预先创建一定数量的连接(由 minIdle 参数指定),以确保在请求到来时能够快速响应,避免因为连接创建而导致延迟。

在 Apache Commons Pool 中,预热机制通过以下参数实现:

  1. minIdle: 定义了连接池中保持的最小空闲连接数。如果空闲连接少于这个值,连接池会主动补充连接。
  2. timeBetweenEvictionRunsMillis: 定义了空闲对象检测线程的运行周期。如果设置了该值,后台线程会定期运行,确保空闲连接数不低于 minIdle
  3. numTestsPerEvictionRun: 定义每次检测时要检查的对象数量。

2. 如何启用预热机制

步骤 1: 设置 minIdle

  • 定义连接池的最小空闲连接数。例如,如果你的系统需要至少保持 5 个连接可以快速响应:
    poolConfig.setMinIdle(5);
    

步骤 2: 启用空闲检测线程

  • 设置 timeBetweenEvictionRunsMillis,让连接池定期检查和补充空闲连接。例如:
    poolConfig.setTimeBetweenEvictionRunsMillis(10000); // 每 10 秒运行一次检测任务
    

步骤 3: 确保足够的空闲连接

  • 设置 numTestsPerEvictionRun,控制每次检测的对象数量。通常设置为一个较大的值(如 -1,表示检测所有对象):
    poolConfig.setNumTestsPerEvictionRun(-1);
    

可选参数

  • testWhileIdle:
    • 如果设置为 true,连接池会在补充空闲连接时验证连接是否有效。
    • 适合场景:如果连接容易失效(例如网络中断),启用此参数可提高连接池的可靠性。

3. 完整的预热机制代码示例

以下是一个示例,展示如何为连接池启用预热机制:

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;public class GrpcChannelPoolConfig {public static GenericObjectPoolConfig<Object> createConfig() {GenericObjectPoolConfig<Object> poolConfig = new GenericObjectPoolConfig<>();// 设置连接池大小poolConfig.setMaxTotal(50);    // 最大连接数poolConfig.setMinIdle(5);      // 最小空闲连接数poolConfig.setMaxIdle(10);     // 最大空闲连接数// 启用预热机制poolConfig.setTimeBetweenEvictionRunsMillis(10000); // 每 10 秒检测一次poolConfig.setNumTestsPerEvictionRun(-1);           // 每次检测所有对象poolConfig.setTestWhileIdle(true);                  // 检查空闲连接有效性return poolConfig;}
}

4. 预热机制的优点

  1. 减少首次延迟:在请求到达前已创建好足够的连接,无需等待连接创建。
  2. 提高系统响应能力:尤其在负载波动较大的场景下,预热机制能缓解连接不足的问题。
  3. 提升可靠性:通过定期检测和补充空闲连接,确保池中连接始终处于健康状态。

5. 注意事项

  1. 监控连接数量

    • 如果设置了过大的 minIdle,可能导致资源浪费(如内存、数据库连接等)。
    • 建议通过监控工具(如 JMX)观察实际连接使用情况,动态调整参数。
  2. 创建时间消耗

    • 如果连接创建耗时较长(如 SSL 或远程服务连接),建议适当增加 timeBetweenEvictionRunsMillis 的间隔,避免频繁创建。
  3. 避免过度销毁

    • 配置 maxIdleminIdle 的差距不宜过大,防止频繁的连接创建和销毁。

6. 总结

预热机制的核心是通过配置 minIdle 和空闲检测线程定期补充连接,以确保空闲连接数不低于 minIdle。启用预热机制的关键配置是:

  1. setMinIdle:定义最小空闲连接数。
  2. setTimeBetweenEvictionRunsMillis:定期检测周期。
  3. 可选:启用 testWhileIdle 提高连接有效性检测。

这些参数协同工作,可以显著提高连接池的性能和响应能力。



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/892173.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小程序开发-页面事件之上拉触底实战案例

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

STM32-笔记38-I2C-oled实验

一、什么是I2C&#xff1f; I2C总线&#xff0c;全称Inter-Integrated Circuit&#xff08;互连集成电路&#xff09;&#xff0c;是一种由Philips&#xff08;现NXP半导体&#xff09;公司在1980年代初开发的同步 串行 半双工通信总线。 二、有了串口通信为什么要使用I2C&…

《C++11》右值引用深度解析:性能优化的秘密武器

C11引入了一个新的概念——右值引用&#xff0c;这是一个相当深奥且重要的概念。为了理解右值引用&#xff0c;我们需要先理解左值和右值的概念&#xff0c;然后再理解左值引用和右值引用。本文将详细解析这些概念&#xff0c;并通过实例进行说明&#xff0c;以揭示右值引用如何…

libevent定时器的性能测试(与rte_timer对比)

前言 接着上篇文章&#xff0c;rte_timer的性能测试https://blog.csdn.net/jacicson1987/article/details/144997298 进行常用的libevent的定时器测试&#xff0c;看看有什么区别&#xff0c;测试方法还是一样&#xff0c;代码放在下面。 测试方法 100万个定时器&#xff0…

C# 事件

目录 1、事件模型的5个组成部分2、使用内置委托类型声明事件2.1 EventHandler2.1.1 &#xff1f;2.1.2 this2.1.3 使用匿名函数和lamda表达式2.1.3.1 匿名函数2.1.3.2 lamda表达式 2.1.4 异常处理 2.2 EventHandler<TEventArgs> 3、使用自定义委托类型声明事件3.1 事件的…

英伟达 RTX 5090 显卡赋能医疗大模型:变革、挑战与展望

一、英伟达 RTX 5090 与 RTX 4090 技术参数对比 1.1 核心架构与制程工艺 在探讨英伟达 RTX 4090 与 RTX 5090 的差异时&#xff0c;核心架构与制程工艺无疑是最为关键的基础要素&#xff0c;它们从根本上决定了两款显卡的性能上限与应用潜力。 1.1.1 核心架构差异 RTX 4090…

爬虫学习记录

1.概念 通过编写程序,模拟浏览器上网,然后让其去互联网上抓取数据的过程 通用爬虫:抓取的是一整张页面数据聚焦爬虫:抓取的是页面中的特定局部内容增量式爬虫:监测网站中数据更新的情况,只会抓取网站中最新更新出来的数据 robots.txt协议: 君子协议,网站后面添加robotx.txt…

玩机搞机基本常识-------列举安卓机型一些不常用的adb联机命令

前面分享过很多 常用的adb命令&#xff0c;今天分享一些不经常使用的adb指令。以作备用 1---查看当前手机所有app包名 adb shell pm list package 2--查看当前机型所有apk包安装位置 adb shell pm list package -f 3--- 清除指定应用程序数据【例如清除浏览器应用的数据】 …

【25考研】川大计算机复试情况,重点是啥?怎么准备?

24年进入复试的同学中&#xff0c;有10位同学的复试成绩为0分。具体是个人原因还是校方原因&#xff0c;还尚不明确。但是C哥提醒&#xff0c;一定要认真复习&#xff01;复试完后不要跟任何人讨论有关复试的题目及细节&#xff01; 一、复试内容 四川大学复试内容较多&#xf…

计算机的错误计算(二百零五)

摘要 基于一位读者的问题&#xff0c;提出题目&#xff1a;能用数值计算证明 吗&#xff1f;请选用不同的点&#xff08;即差别大的数&#xff09;与不同的精度。实验表明&#xff0c;大模型理解了题意。但是&#xff0c;其推理能力值得商榷。 例1. 就摘要中问题&#xff0…

回归预测 | MATLAB实GRU多输入单输出回归预测

回归预测 | MATLAB实GRU多输入单输出回归预测 目录 回归预测 | MATLAB实GRU多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB实GRU多输入单输出回归预测。使用GRU作为RNN的一种变体来处理时间序列数据。GRU相比传统的RNN有较好的记…

unity学习12:地图相关的一些基础2, 增加layer种草种树

目录 参考学习 1 地图设置 1.1 上次制作的地图&#xff0c;稍微加点地形完善下. 1.2 调整下camera 1.3 摄像机camera的移动速度 1.4 地图属性&#xff0c;terrain settings 1.5 但是&#xff0c;地图看起来像沙漠一样&#xff0c;很单调 2 paint terrain / paint textu…

数据挖掘——数据预处理

数据挖掘——数据预处理 数据预处理数据预处理 ——主要任务数据清洗如何处理丢失的数据如何处理噪声数据如何处理不一致数据 数据集成相关分析相关系数(也成为皮尔逊相关系数)协方差 数据规约降维法&#xff1a;PCA主成分分析降数据——抽样法数据压缩 数据预处理 数据预处理…

Python入门教程 —— 网络编程

1.网络通信概念 简单来说,网络是用物理链路将各个孤立的工作站或主机相连在一起,组成数据链路,从而达到资源共享和通信的目的。 使用网络的目的,就是为了联通多方然后进行通信,即把数据从一方传递给另外一方。 前面的学习编写的程序都是单机的,即不能和其他电脑上的程…

鸿蒙APP之从开发到发布的一点心得

引言&#xff1a; 做鸿蒙开发大概有1年左右时间了&#xff0c;从最开始的看官方文档、看B站视频&#xff0c;到后来成功发布两款个人APP&#xff08;房贷计算极简版、时简时钟 轻喷&#xff0c;谢谢&#xff09;。简单描述一下里边遇到的坑以及一些经历吧。 学习鸿蒙开发 个…

力扣刷题:数组OJ篇(上)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 目录 1.消失的数字&#xff08;1&#xff09;题目描…

linux下多个硬盘划分到同一挂载点

Linux下多个硬盘划分到同一挂载点 需要明确的几个概念 物理卷: 物理卷是物理存储设备&#xff08;如硬盘分区、整个硬盘、RAID 阵列等&#xff09;在逻辑卷管理&#xff08;LVM - Logical Volume Manager&#xff09;系统中的抽象表示。它是构建逻辑卷组的基本单元 假设我们有…

2.STM32F407ZGT6-外部中断

参考&#xff1a; 1.正点原子。 前言&#xff1a; MCU最重要的一个领域–中断。总结下嵌套向量和外部中断的概念。达到&#xff1a; 1.NVIC是什么&#xff0c;了解中断的整体管理理念。 2.中断里面最简单的外部中断&#xff0c;怎么配置处理。 3.使用STM32CubeMX配置外部中断的…

《HeadFirst设计模式》笔记(下)

代理模式 代理要做的就是控制和管理访问。 你的客户对象所做的就像是在做远程方法调用&#xff0c;但其实只是调用本地堆中的“代理”对象上的方法&#xff0c;再由代理处理所有网络通信的低层细节。 Java的RMI提供了客户辅助对象和服务辅助对象&#xff0c;为客户辅助对象…

【学Rust开发CAD】1 环境搭建

文章目录 一、搭建C/C编译环境二、安装Rust三、配置 PATH 环境变量四、验证安装结果五、安装编辑工具 一、搭建C/C编译环境 Rust 的编译工具依赖 C 语言的编译工具&#xff0c;这意味着你的电脑上至少已经存在一个 C 语言的编译环境。如果你使用的是 Linux 系统&#xff0c;往…