news 2026/9/23 18:48:03

Ceph OSD 与 Placement Group(PG)监控与故障排查实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ceph OSD 与 Placement Group(PG)监控与故障排查实战指南
  • 存储
  • 分布式文件系统
  • 对象存储
  • 后端
  • 高可用

【免费下载链接】ceph

Ceph is a distributed object, block, and file storage platform

项目地址:https://gitcode.com/gh_mirrors/ce/ceph
点击查看免费下载

Ceph 是一个分布式对象、块与文件存储平台,其高可用与高可靠性建立在容错式的软硬件故障管理之上。本指南围绕 Ceph 集群中两个最关键的监控对象——OSD(Object Storage Daemon,对象存储守护进程)与 PG(Placement Group,放置组)——展开,系统讲解 OSD 的in/outup/down状态语义、PG 的完整状态机(从creatingactive+clean)、Acting Set / Up Set 集合、Peering 过程以及 stuck 问题 PG 的识别方法。读完本文,你将掌握一套可直接落地的监控命令集(ceph osd statceph osd treeceph pg statceph pg dump_stuckceph osd map等),并能结合相关配置参数(mon_osd_down_out_intervalosd_max_backfillsosd_recovery_max_active等)读懂集群健康状态、定位故障根源并做出初步处置。

先记住一条原则:集群某处发生故障,可能使你无法访问某个特定对象,但这并不代表你无法访问其他对象。遇到故障时不要惊慌,按本文的步骤依次监控 OSD 和放置组,再开始故障排查。Ceph 具备自我修复能力,但当问题持续存在时,监控 OSD 和 PG 将帮助你定位问题所在。

OSD 状态模型:in/outup/down的四象限

Ceph 中每个 OSD 都同时具有两个正交的状态维度:

  • in/out(服务状态):OSD 是否在集群服务范围内。in表示该 OSD 处于服务中,客户端可以读写其上的数据;out表示该 OSD 已退出服务,CRUSH 不会再为其分配 PG。
  • up/down(运行状态):OSD 守护进程是否正在运行且可被访问。up表示运行中且可达,down表示未运行或不可达。

两者组合形成如下状态矩阵(原文档 ditaa 示意图的文本版):

+----------------+ +----------------+ | OSD #n In | | OSD #n Up | +----------------+ +----------------+ ^ ^ | | v v +----------------+ +----------------+ | OSD #n Out | | OSD #n Down | +----------------+ +----------------+

需要理解的关键语义:

  • 若 OSD 曾是in,后因故障或人工操作被置为out,Ceph 会将 PG 迁移到其他 OSD 以维持配置的冗余度。
  • 若 OSD 是out,CRUSH 将不再向其分配 PG;若 OSD 是down,它必然同时是out
  • downin是一个异常组合:一旦出现这种情况,说明该 OSD 未运行却在服务范围内,集群处于不健康状态。

何时集群不显示HEALTH OK是正常的?

运行ceph healthceph -sceph -w时,你可能会发现集群并不总是显示HEALTH OK。以下情形属于预期内、正常的非健康状态,无需恐慌:

  1. 集群尚未启动。
  2. 集群刚启动或重启,PG 正在创建、OSD 正在 Peering,尚未就绪。
  3. 刚刚添加或移除了 OSD。
  4. 刚刚修改了集群地图(cluster map)。

监控 OSD:确认每个in的 OSD 都在运行

OSD 是否up且正在运行,是监控 OSD 的重要方面:只要集群处于运行状态,每个处于in状态的 OSD 都应当是up的。检查全部 OSD 运行状态,执行:

ceph osd stat

输出格式为x osds: y up, z in; epoch: eNNNN,含义如下:

字段含义
x集群中 OSD 的总数
y处于up状态的 OSD 数
z处于in状态的 OSD 数
eNNNN当前 osdmap 的 epoch(地图版本号)

in的数量大于up的数量,说明有ceph-osd守护进程未运行。用以下命令找出具体是哪些:

ceph osd tree

示例输出:

#ID CLASS WEIGHT TYPE NAME STATUS REWEIGHT PRI-AFF -1 2.00000 pool openstack -3 2.00000 rack dell-2950-rack-A -2 2.00000 host dell-2950-A1 0 ssd 1.00000 osd.0 up 1.00000 1.00000 1 ssd 1.00000 osd.1 down 1.00000 1.00000

ceph osd tree以 CRUSH 层次结构(pool → rack → host → osd)展示每个 OSD 的STATUS列(up/down)、REWEIGHTPRI-AFF(主亲和性)。排查技巧:善用设计良好的 CRUSH 层次结构来定位特定 OSD 的物理位置,能显著加速故障定位。

若某个 OSD 处于down状态,用 systemd 启动它(以osd.1为例):

sudo systemctl start ceph-osd@1

对于 OSD 已停止或无法重启的问题,参见 OSD Not Running 排查文档。

PG 集合:Acting Set 与 Up Set

当 CRUSH 将 PG 分配给 OSD 时,会根据池所需的副本数,把每个副本分配到不同的 OSD上。例如池要求 3 个副本时,CRUSH 可能将三个副本分别分配给osd.1osd.2osd.3。CRUSH 追求的是考虑了你所设置的故障域的伪随机放置,因此在大型集群中,PG 的各个副本很少落在相邻的 OSD 上。

Ceph 用两组集合描述 PG 与 OSD 的关系:

  • Acting Set(执行集合):当前持有该 PG 分片完整且可用版本、负责处理客户端请求的 OSD 集合。
  • Up Set(上行集合):包含该 PG 某一分片的 OSD 集合。数据正在被迁移、或计划被迁移到 Up Set。

更多背景参见 Placement Group 概念。

何时 Acting Set 与 Up Set 不一致?通常情况下两者完全相同。当它们不一致时,可能意味着:

  • Ceph 正在迁移 PG(即 PG 被 remapped);
  • 某个 OSD 正在恢复(recovering);
  • 集群存在问题(此时 Ceph 通常会显示HEALTH WARN并伴随 "stuck stale" 消息)。

另一种常见情形是 Acting Set 中的某个 OSDdown或无法服务请求,例如:

  • 你添加或移除了 OSD,CRUSH 将 PG 重新分配给其他 OSD,重组了 Acting Set,并通过backfill(背填)流程触发数据迁移;
  • 某个 OSDdown后重启,正处于recovering状态;
  • Acting Set 中某个 OSDdown或无法服务请求,另一个 OSD 临时接管了它的职责。

列出集群所有 PG:

ceph pg dump

查看某个 PG 的 Acting Set 与 Up Set:

ceph pg map {pg-num}

输出提供 osdmap epoch(eNNN)、PG 编号({pg-num})、Up Set(up[])与 Acting Set(acting[]):

osdmap eNNN pg {raw-pg-num} ({pg-num}) -> up [0,1,2] acting [0,1,2]

注意:若 Up Set 与 Acting Set 不匹配,可能意味着集群正在自我再平衡,也可能意味着集群存在问题。

Peering:PG 进入active状态的前提

在向 PG 写入数据之前,PG 必须处于active状态,且最好处于clean状态。为了确定 PG 的当前状态,必须执行Peering(对等):即 PG 的 primary OSD(Acting Set 中的第一个 OSD)与 secondary 及其后续 OSD 进行对等协商,就 PG 的当前状态达成共识。下图假设池有 3 个副本:

+---------+ +---------+ +-------+ | OSD 1 | | OSD 2 | | OSD 3 | +---------+ +---------+ +-------+ | | | | Request To | | | Peer | | |-------------->| | |<--------------| | | Peering | | | | | | Request To | | Peer | |----------------------------->| |<-----------------------------| | Peering |

OSD 同时也会向 monitor 上报自身状态,相关机制参见 Monitor/OSD 交互配置。Peering 故障排查参见 failures-osd-peering。

监控 PG 状态

运行ceph healthceph -sceph -w时,集群可能不显示HEALTH OK。在确认 OSD 运行正常之后,还应当检查 PG 状态。以下与 PG 对等相关的场景中,集群不显示HEALTH OK是正常现象:

  1. 刚刚创建了池,PG 尚未完成 Peering;
  2. PG 正在恢复(recovering);
  3. 刚刚向集群添加或移除了 OSD;
  4. 刚刚修改了 CRUSH 地图,PG 正在迁移;
  5. PG 的不同副本之间存在不一致数据;
  6. Ceph 正在对 PG 的副本执行 scrub(清理/校验);
  7. Ceph 没有足够的存储容量完成背填(backfill)操作。

这些情形导致HEALTH WARN时不必恐慌,多数情况下集群会自行恢复;但某些情况下需要人工介入。监控 PG 的重点是检查其状态是否为activeclean:即集群运行时,所有 PG 都应处于active状态,且最好是clean

查看每个 PG 的状态:

ceph pg stat

输出格式为x pgs: y active+clean; z bytes data, aa MB used, bb GB / cc GB avail,含义:

字段含义
xPG 总数
y处于某特定状态(如active+clean)的 PG 数
z已存储的数据量
aa已使用的存储容量
bb剩余可用存储容量
ccPG 总存储容量

注意:Ceph 经常为一个 PG 同时报告多个状态,例如active+cleanactive+clean+remappedactive+clean+scrubbing等。

容量信息(已用aa、剩余bb、总量cc)在以下场景中尤其重要:

  • 集群正接近near full ratio(接近满阈值)或full ratio(满阈值);
  • 由于 CRUSH 配置错误,数据未能在集群中均匀分布。

PG ID 的构成

PG ID 由池编号(注意是编号而非池名)加句点.加十六进制数组成。通过ceph osd lspools可查看池编号与池名的对应关系。例如第一个创建的池对应池编号1。完整的 PG ID 形式为:

{pool-num}.{pg-id}

典型示例:

1.1701b

查询 PG 的常用命令

列出所有 PG:

ceph pg dump

以 JSON 格式输出并保存到文件:

ceph pg dump -o {filename} --format=json

查询特定 PG 的详细信息(Ceph 以 JSON 格式输出):

ceph pg {poolnum}.{pg-id} query

例如查询池1中 PG1701b的详情:ceph pg 1.1701b query

常见 PG 状态详解

Ceph 在源码 src/osd/osd_types.h 中以位掩码定义了各 PG 状态(如PG_STATE_ACTIVEPG_STATE_CLEANPG_STATE_DEGRADEDPG_STATE_RECOVERINGPG_STATE_BACKFILL_WAITPG_STATE_BACKFILLINGPG_STATE_INCOMPLETEPG_STATE_STALEPG_STATE_REMAPPED),多个状态位可同时置位,这正是active+cleanactive+clean+remapped这类组合状态名称的由来。以下按 PG 生命周期逐个讲解。

Creating(创建中)

创建池时即创建 PG:创建池的命令会指定该池的 PG 总数,池创建后所有 PG 一并创建。创建期间 Ceph 会回显creating。PG 创建完成后,其 Acting Set 中的 OSD 开始 Peering;Peering 完成后,PG 状态应变为active+clean,此时 Ceph 客户端开始向该 PG 写入数据。

/-----------\ /-----------\ /-----------\ | Creating |------>| Peering |------>| Active | \-----------/ \-----------/ \-----------/

Peering(对等中)

PG 对等时,存储其数据副本的 OSD 就 PG 内的数据与元数据收敛到一致状态。对等完成后,这些 OSD 对该 PG 的状态达成共识。但需要注意:对等过程完成并意味着每个副本都已拥有最新内容。

关于**权威历史(Authoritative History)**的机制说明:

  • 在 Acting Set 中每个 OSD 都持久化了某次写操作之前,Ceph 不会向客户端确认(acknowledge)该写操作。这保证了自上次成功对等以来,Acting Set 中至少有一个成员保留着每一次已确认写操作的记录。
  • 凭借准确的已确认写操作记录,Ceph 可以构造出该 PG 的新的权威历史——即一整套完整且全序的操作序列,按序执行即可让某个 OSD 上的 PG 副本追上最新状态。

Active(活跃)

Ceph 完成对等后,PG 应变为activeactive状态意味着该 PG 中的数据在 primary 和副本 OSD 上通常可进行读写操作。

Clean(干净)

PG 处于clean状态时,所有持有其数据与元数据的 OSD 都已成功对等,且不存在 stray(游离)副本;Ceph 已将该 PG 中的所有对象复制了正确次数。

Degraded(降级)

客户端向 primary OSD 写入对象后,primary 负责把副本写到副本 OSD。在 primary 将对象写入存储后,PG 会保持degraded状态,直到 primary 收到副本 OSD 确认成功创建副本对象的回执。

PG 可能处于active+degraded的原因:OSD 即使尚未持有 PG 的全部对象也可以保持active。若某 OSDdown,Ceph 会将该 OSD 上每个 PG 标记为degraded;该 OSD 恢复上线后,PG 必须重新对等。但只要 PG 是active的,客户端仍可向其写入新对象。

downout的自动转换:若 OSDdowndegraded状态持续存在,Ceph 可能将该down的 OSD 标记为out,并把数据从它 remap 到其他 OSD。从标记down到标记out的时间由mon_osd_down_out_interval决定,默认600 秒(10 分钟)。在源码 src/common/options/mon.yaml.in 中该参数定义明确为 "mark any OSD 'out' that has been 'down' for this long (seconds)",默认值10_min,服务对象为 monitor。与之配合的还有mon_osd_down_out_subtree_limit(默认rack,即整个机架子树全挂时不自动标记 out)与mon_osd_min_up_ratio(up 比例过低时不自动标记 out),这些防御性参数可避免级联故障时 OSD 被批量踢出集群。

另一种进入degraded的途径:PG 中存在一个或多个 Ceph 期望找到却找不到的对象(unfound objects)。虽然无法读写这些 unfound 对象,但degradedPG 中的其他对象仍可正常访问。

Recovering(恢复中)

Ceph 天生为容错而设计,硬件与其他服务器问题被视作常态。当 OSDdown时,其内容可能落后于 PG 中其他副本的当前状态;OSD 回到up后,必须将 PG 内容更新到当前状态,此期间 OSD 可能处于recovering状态。

恢复并非总是轻而易举:一次硬件故障可能引发多个 OSD 的级联故障。例如某个机架或机柜的交换机故障,可能导致多台主机上的 OSD 同时落后于集群当前状态。此类场景下,只有每个 OSD 都在故障解除后恢复,整体恢复才可能完成。

Ceph 提供多个参数来权衡"处理新服务请求"与"恢复数据对象、把 PG 恢复到最新状态"之间的资源竞争:

参数作用默认值(源码依据)
osd_recovery_delay_start允许 OSD 重启、重新对等、处理部分 replay 请求后再启动恢复0(osd.yaml.in)
osd_recovery_thread_timeout确定恢复线程的超时时长(多个 OSD 可能以交错速率失败、重启、重新对等)文档描述值
osd_recovery_max_active限制 OSD 同时处理的恢复请求数,防止 OSD 无法继续服务0(非零才生效;实际按磁盘类型取 hdd/ssd 值,osd.yaml.in)
osd_recovery_max_active_hdd机械盘(rotational)主设备 OSD 的同时恢复请求数3(osd.yaml.in)
osd_recovery_max_active_ssdSSD(非旋转介质)主设备 OSD 的同时恢复请求数10(osd.yaml.in)
osd_recovery_max_chunk限制恢复数据块的大小,防止网络拥塞size 类型(osd.yaml.in)

其中osd_recovery_max_active默认值为0,此时实际生效的是按主设备类型区分的osd_recovery_max_active_hdd/osd_recovery_max_active_ssd;只有显式设为非零值时才覆盖二者。另外注意:mClock 调度器激活时,这些恢复/背填上限通常不可修改(详见下文 Backfilling 一节的说明)。

Backfilling(背填)

新 OSD 加入集群时,CRUSH 会把集群中已有 OSD 上的 PG 重新分配给新 OSD。若强制新 OSD 立即接受被重新分配的 PG,会给它带来过大负载;backfill(背填)允许该过程在后台进行。背填完成后,新 OSD 一旦就绪即可开始服务请求。

背填期间可能看到的状态:

  • backfill_wait:背填操作已排队但尚未开始;
  • backfilling:背填操作正在进行中;
  • backfill_toofull:请求了背填但因存储容量不足无法完成。该状态可能是暂时性的——随着 PG 被搬移腾出空间,条件变化后即可继续,这与backfill_wait类似;
  • 当 PG 无法被背填时,可能被视为incomplete(不完整)。

Ceph 提供多个参数管理 PG 重新分配(尤其是新 OSD)带来的负载尖峰:

参数作用默认值(源码依据)
osd_max_backfills指定单个 OSD 并发背填(进/出)的最大数量1(osd.yaml.in)
backfill_full_ratioOSD 接近 full ratio 时拒绝背填请求90%,可用ceph osd set-backfillfull-ratio修改
osd_backfill_retry_interval背填被拒绝后的重试间隔30秒(osd.yaml.in)
osd_backfill_scan_min每次背填扫描的最小对象数64(osd.yaml.in)
osd_backfill_scan_max每次背填扫描的最大对象数512(osd.yaml.in)

关于osd_max_backfills与 mClock:若 mClock 调度器 处于激活状态,默认情况下不能修改osd_max_backfills(同理还有osd_recovery_max_active_hddosd_recovery_max_active_ssd),除非设置osd_mclock_override_recovery_settings = true——源码 osd.yaml.in 明确记录了这一限制。mClock 下的背填调优参见 mClock recovery/backfill 选项。

backfill_full_ratio命令存在于ceph osd set-backfillfull-ratio,在 src/mon/MonCommands.h 中定义,参数类型为CephFloat,取值范围0.0|1.0,语义为 "set usage ratio at which OSDs are marked too full to backfill"。

Remapped(重映射)

当服务某 PG 的 Acting Set 发生变化时,数据从旧 Acting Set 迁移到新 Acting Set。由于新 primary OSD 开始服务请求可能需要时间,旧 primary 可能被要求继续服务请求,直到 PG 数据迁移完成。数据迁移完成后,映射使用新 Acting Set 的 primary OSD。

Stale(陈旧)

Ceph 使用心跳(heartbeat)确保主机与守护进程在运行,但ceph-osd守护进程可能进入stuck(卡住)状态,无法及时上报统计信息(例如发生临时网络故障)。默认情况下,OSD 守护进程每0.5 秒上报一次 PG、up-through、boot 与失败统计,频率高于心跳阈值定义的报告间隔。若 PG 的 Acting Set 中 primary OSD 未能向 monitor 上报,或其它 OSD 已上报该 primarydown,monitor 就会将该 PG 标记为stale

集群启动时看到stale状态很常见,直到对等过程完成。但集群运行一段时间后仍出现stale,则说明这些 PG 的 primary OSD 已down或未向 monitor 上报 PG 统计信息。

识别问题 PG:stuck 状态排查

如前所述,PG 状态不是active+clean并不代表一定有问题。但当 PG卡住(stuck)时,可能意味着 Ceph 无法执行自我修复。三种 stuck 状态:

状态含义
Unclean(不干净)PG 包含未按期望次数复制的对象。正常情况下可假定这些 PG 正在恢复(recovering)。
Inactive(不活跃)PG 无法处理读写,因为它在等待持有最新数据的 OSD 回到up
Stale(陈旧)PG 处于未知状态,因为托管它们的 OSD 在特定时间段(由mon_osd_report_timeout决定)内未向 monitor 集群上报。

mon_osd_report_timeout在源码 src/common/options/global.yaml.in 中的语义是"OSD 未向 mons 上报则被标记为 down 的宽限时间(秒)",默认值15_min(15 分钟),服务对象为 monitor。

识别卡住的 PG:

ceph pg dump_stuck [unclean|inactive|stale|undersized|degraded]

更多背景参见 Placement Group 子系统(ceph pg命令总览)。stuck PG 的完整排查流程参见 failures-pg-stuck。

定位对象位置:从对象名到 PG 再到 OSD

要在 Ceph Object Store 中存储对象数据,Ceph 客户端必须:

  1. 设定对象名(object name);
  2. 指定一个池(pool)。

Ceph 客户端获取最新集群地图后,CRUSH 算法先计算如何把对象映射到 PG,再计算如何把 PG 动态分配到 OSD。仅凭对象名与池名即可定位对象:

ceph osd map {poolname} {object-name} [namespace]

练习:定位一个对象

第一步,用rados put创建对象,指定对象名、测试文件路径与池名:

rados put {object-name} {file-path} --pool=data rados put test-object-1 testfile.txt --pool=data

验证对象已存入 Ceph Object Store:

rados -p data ls

定位对象的存放位置:

ceph osd map {pool-name} {object-name} ceph osd map data test-object-1

Ceph 应输出对象位置,例如:

osdmap e537 pool 'data' (1) object 'test-object-1' -> pg 1.d1743484 (1.4) -> up ([0,1], p0) acting ([0,1], p0)

该输出依次给出:osdmap epoch(e537)、池名与池编号('data' (1))、对象名、对象所属的 PG(完整 PG ID1.d1743484与短形式1.4)、以及该 PG 的 Up Set([0,1],primary 为p0)与 Acting Set([0,1],primary 为p0)。

清理测试对象:

rados rm test-object-1 --pool=data

随着集群演进,对象位置可能动态变化。Ceph 动态再平衡的一大好处,就是省去了人工执行迁移的负担,相关机制详见 架构文档。这种"对象 → PG → OSD"的两级间接映射,也正是数据放置(data placement)的核心设计:数据不直接绑定到特定 OSD,因此故障时只需在 PG 与底层 OSD 层面追踪问题即可。

监控实战小结

把整套监控动作串成一条排查主线:

  1. 看全局ceph -s/ceph health/ceph -w,确认是否为HEALTH_OK之外的预期状态;
  2. 查 OSDceph osd stat对比inup数量,ceph osd tree定位down的 OSD,必要时sudo systemctl start ceph-osd@N
  3. 查 PGceph pg stat查看状态分布,ceph pg dump/ceph pg dump -o {file} --format=json导出明细,ceph pg {poolnum}.{pg-id} query深查单个 PG;
  4. 找卡住的 PGceph pg dump_stuck [unclean|inactive|stale|undersized|degraded],对照mon_osd_report_timeout(默认 15 分钟)与mon_osd_down_out_interval(默认 600 秒)等参数判断是"正在自我恢复"还是"需要人工介入";
  5. 定位对象ceph osd map {poolname} {object-name}把对象、PG、OSD 三层映射关系串起来,结合 troubleshooting-osd 与 troubleshooting-pg 进行根因分析。

理解 OSD 状态四象限、PG 生命周期状态机以及 Acting Set / Up Set 的含义,是读懂上述所有命令输出的基础。Ceph 是自修复系统,多数非HEALTH OK状态会随对等、恢复、背填的完成而自行消退;只有当 PG 长期 stuck、副本持续 degraded 或容量达到阈值时,才需要依据本文的参数调优与排查路径进行人工干预。

  • 存储
  • 分布式文件系统
  • 对象存储
  • 后端
  • 高可用

【免费下载链接】ceph

Ceph is a distributed object, block, and file storage platform

项目地址:https://gitcode.com/gh_mirrors/ce/ceph
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 18:46:14

Spring Boot电影网站实战:MySQL+MyBatis-Plus+Thymeleaf全栈搭建

简介&#xff1a;本资源是一套基于SSM框架与Vue前端的完整电影网站系统源码&#xff0c;面向Java Web初学者及课程设计、毕业设计阶段的学生&#xff0c;解决Web全栈项目从需求分析到部署上线的实践闭环问题。压缩包共880个文件&#xff0c;涵盖144个Java后端逻辑类、53个Vue组…

作者头像 李华
网站建设 2026/9/23 18:45:39

LightGBM-MATLAB轻量级封装:原生C++调用与高效部署指南

简介&#xff1a;本资源是面向MATLAB用户的数据科学实践工具包&#xff0c;专为在MATLAB环境中高效调用LightGBM轻量级梯度提升机而设计&#xff0c;适用于机器学习初学者、算法工程师及科研人员解决分类、回归等大规模建模任务。压缩包共7个文件&#xff0c;含5个核心MATLAB函…

作者头像 李华
网站建设 2026/9/23 18:44:23

Unity3D运行时OBJ模型导入与碰撞体生成完整实现

简介&#xff1a;面向Unity开发者的运行时模型处理源码工程&#xff0c;解决在游戏运行阶段动态导入外部模型文件、实时编辑其位置、旋转、缩放及碰撞体信息并持久化保存的完整需求。工程整合TriLib模型加载插件与RuntimeTransformGizmos操作插件&#xff0c;同时提供数值输入面…

作者头像 李华
网站建设 2026/9/23 18:43:31

Dart SDK 中 FFI 基准测试原生库的构建与 CIPD 发布流程指南

编程语言编译器语言运行时标准库开发工具 【免费下载链接】sdk The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/sdk1/sdk 点击查看 免费下载 本文以 Dart SDK 仓库中的 b…

作者头像 李华