ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Perfetto 多机追踪架构深度解析:traced_relay、机器身份与跨内核时钟同步

Perfetto 多机追踪架构深度解析:traced_relay、机器身份与跨内核时钟同步 Perfetto 多机追踪架构深度解析traced_relay、机器身份与跨内核时钟同步【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto导读多机追踪Multi-machine tracing是 Perfetto 面向复杂软件系统的一项能力它能把分布在多台操作系统镜像宿主机与虚拟机、SoC 与协处理器、多台测试机组成的集群上的事件录制成一条单一 trace在一个统一时间轴上呈现并可用 SQL 查询跨机因果关系。本文将基于仓库中的架构文档结合traced_relay、traced与 Trace Processor 的源码实现讲清多机追踪是什么、各部件如何配合记录的具体步骤见 Multi-machine recording读完后你将掌握 relay 转发模型、机器身份machine_id机制、跨内核时钟同步原理以及数据源分发配置等关键实现细节。问题陈述单机服务模型为何在多机场景失效Perfetto 标准的 service model 隐含一个前提所有 producer、traced服务与 consumer 共享同一个操作系统镜像。它们通过本地 UNIX socket 访问traced共享同一个 PID 命名空间并观察同一个CLOCK_BOOTTIME时钟。一旦某个 producer 跑在另一个内核上这个前提立即被打破没有共享的 filesystem socket——UNIX socket 无法跨内核访问PID 命名空间相互独立——同一 PID 在不同机器上指代不同进程boot 时钟起点不同且各自漂移——CLOCK_BOOTTIME的零点因内核而异无法直接比较。一种朴素的做法是在每台机器上各自运行traced录完再用 merging-traces 事后合并。但这种方式下跨机器时钟对齐的精度只取决于各机器墙钟同步或手动提供的偏移量对任何时间敏感的分析如跨机调度、RPC 时延都不够可靠。Live 多机追踪live multi-machine tracing的解决思路是在录制期间实时测量时钟偏移且不需要在每台机器上复制 buffer 和 consumer 机制。这正是本文介绍的核心架构。整体架构一台 host 的 traced 所有远程机器的 traced_relay多机设置中恰好一台机器运行traced即 host其余每台机器运行traced_relay把 producer 侧 IPC 转发到 host。文档中的架构图如下Remote machine Host machine ┌────────────────────────┐ ┌────────────────────────────┐ │ traced_probes │ │ traced --enable-relay- │ │ other producers │ │ endpoint │ │ │ │ │ ▲ │ │ ▼ (local IPC) │ TCP/vsock │ │ (local IPC) │ │ traced_relay ────────┼──────────────►│ relay endpoint │ └────────────────────────┘ │ ▲ │ │ │ │ │ traced_probes / other │ │ local producers │ │ ▲ │ │ │ (consumer IPC) │ │ perfetto cmdline │ └────────────────────────────┘关键角色与职责划分tracedhost 侧通过--enable-relay-endpoint在 producer socket 上额外开放 relay endpoint接受远程traced_relay连接traced_relay远程机器侧在本地 producer socket 上接受 producer 连接与 host 交换少量元数据后把 producer IPC 帧通过TCP 或 vsock代理到 hostconsumerperfetto命令行或 UI 的 WebSocket bridge永远只与 host 的traced通信。Trace 配置、buffer 所有权、最终读回都集中在单台机器上。traced_relay 的刻意轻薄设计从 src/traced_relay/ 目录的源码结构看traced_relay的实现刻意保持最小化relay_service_main.cc 只是入口直接调用perfetto::RelayServiceMain()relay_service.h 定义RelayService与RelayClient两个核心类socket_relay_handler.h 负责 socket 间的帧转发。它不缓冲 trace 数据、不解析 trace packet、不实现任何 consumer 侧功能——只做透明的 IPC 代理。RelayClient的职责按 relay_service.h 中的注释可分为四步① 用 client socket name 连接 host支持如vsock://2:10001这样的 vsock 地址② 连接后发送SetPeerIdentity消息让 tracing service 知道本 RelayClient 的机器身份③ 将 socket 交给RelayIPCClientRelayPortRPC 服务的客户端实现④ 任何 socket 错误都会通过OnErrorCallback通知上层RelayService以便重试连接。此外RelayClient还承担与 host 的时间同步职责其阶段状态机Phase::CONNECTING / PING / UPDATE与SendSyncClockRequest()方法体现了下文将介绍的时钟同步流程。这种设计带来的直接好处是buffer 分配、clock snapshot 发出、consumer 读回等复杂逻辑只在 host 上存在一份远程机器上几乎零状态。机器身份SetPeerIdentity 与 machine 表当traced_relay首次连接 host 时会发送一条SetPeerIdentity消息其中包含machine_id_hint。该 hint 的生成逻辑在 relay_service.cc 的RelayService::GetMachineIdHint()中首选读取/proc/sys/kernel/random/boot_idLinux 上可用时否则回退到uname(2)的哈希加上一个 bootup 时间戳来源get_pseudo_boot_id()逻辑。因此该 hint 对同一内核的多次重连是稳定的但在不同内核之间互不相同。host 的traced会把每个唯一 hint 映射为一个小整数MachineId并给从该 relay 到达的每个TracePacket盖上这个标记即TracePacket上的machine_id字段。导入时Trace Processor 为每台机器在machine表中物化一行。其表结构定义见 metadata_tables.pyColumnDescriptionidTrace-Processor 分配的机器 ID。host 恒为0。raw_id来自 trace packet 的原始机器标识host 为0远程机器非零。sysname,release,version,arch该机器的uname(2)字段。num_cpus该内核可见的 CPU 数量。system_ram_bytes,system_ram_gb总内存。android_build_fingerprint,android_device_manufacturer,android_sdk_version仅 Android 机器填充。跨机数据切片凡是带每 CPU 或每线程维度的表thread、cpu、gpu_counter_track等都携带可空的machine_id列因此可以用 SQL 按机器切分数据。例如cpu表通过ucpu全局统一的 CPU 编号关联到具体机器其machine_id列可参与 join。目前 UI 对每机 track 的支持仍在演进中所以machine_idjoin 是回答跨机问题最可靠的方式。跨机器时钟同步轻量 ping 协议与时钟图每台远程机器有自己的CLOCK_BOOTTIME其 producer 写入的时间戳不能与 host 直接比较。traced_relay通过轻量 ping 协议与 host 的 relay endpoint 交互发送并接收带时间戳的消息从而估算每台机器的时钟偏移与往返时间RTT。host 将每台远程机器的成对ClockSnapshot以RemoteClockSyncpacket 的形式写入 trace。从 clock_tracker.cc 的源码可以看出这一机制在导入端的落点时钟 ID 通过ClockId::Qualify(clock_id, machine_id_, ...)进行机器限定machine-qualified使不同机器的同名时钟成为时钟图中的独立节点远程机器的时钟快照被折叠进同一个时钟图中。其后续处理完全复用 Clock Synchronization 中已有的单机机制Trace Processor 把跨机偏移折叠进它本就要为CLOCK_REALTIME、CLOCK_MONOTONIC等构建的时钟图导入时把每个事件解析到单一全局 trace 时钟数据源无需任何额外工作。值得注意的是同一个时钟图同样支撑 post-hoc trace merging事后合并——区别只在于跨机边的来源live 录制来自 ping 协议事后合并来自墙钟 rendezvous 或 perfetto_manifest 清单文件。数据源分发trace_all_machines 与 machine_name_filter默认情况下traced只把数据源分发给 host 机器上的 producer。要从远程机器采集数据consumer 的TraceConfig必须显式选择二选一全局trace_all_machines: true按数据源DataSource.machine_name_filter。若两者都不设置远程机器上的traced_probes虽然仍会注册、并作为machine表的一行出现但永远不会被分配请求的数据源因此不会有任何事件流出。对应 proto 定义见 trace_config.protoDataSource.machine_name_filterrepeated string machine_name_filter 4按机器名过滤。机器名的确定优先级为PERFETTO_MACHINE_NAME环境变量 → Android 系统属性persist.traced_relay.machine_name→uname -s的 utsname sysname如Linux。字面量host是运行traced那台机器的同义词trace_all_machinesoptional bool trace_all_machines 43为true时远程 producer通过traced_relay连接的机器中的数据源默认被匹配为false默认时只匹配 host。显式设置的machine_name_filter优先级更高。版本兼容注意事项trace_all_machines在perfetto v54引入v54 之前的版本默认匹配所有机器。文档建议要跨过这个版本边界保持兼容要么把该字段设为true要么给所有数据源显式设置machine_name_filter。一个容易踩的坑同一内核无法冒充两台机器同一内核上的两个 producer 即使分别注册也不能当作两台机器用于测试。原因在于两个traced_probes实例会竞争同一个/sys/kernel/tracing/ring buffer而 per-CPU 事件会被任意切分到两个machine_id之间——trace 看起来有效实际却静默撕裂silently torn。多机设置必须需要两个内核两台机器、host 加 VM、拥有各自内核命名空间的独立容器等。限制与约束多机架构文档明确列出了以下约束traced_relay不能与traced同机运行——两者都要绑定本地 producer socket。设置中每台机器要么运行tracedhost要么运行traced_relay其余所有机器每台远程机器必须有到达 host relay endpoint 的网络路径TCP 或 vsock跨机器时钟对齐精度取决于 ping 协议对偏移的测量粗略对齐的墙钟NTP 等有助于首批 snapshot但并非严格必需UI 的每机 track 渲染仍在演进当前按机器切分跨机数据的权威方式仍是查询machine表与machine_id列的 SQL。实战速览两台 Linux 主机的多机录制架构文档聚焦是什么与如何拼装具体的逐步操作记录见 Multi-machine recording。这里给出核心流程梗概host运行tracedguest运行traced_relayhost 启动traced并监听 TCP--enable-relay-endpoint让该 socket 同时接受 relay 连接PERFETTO_PRODUCER_SOCK_NAME0.0.0.0:20001 \ tracebox traced --enable-relay-endpoint若还需保留本地 AF_UNIX producer socket可同时列出两个 socket 并用更窄的--enable-relay-endpoint-on指名哪个 socket 承载RelayPort注意该 flag 只是从PERFETTO_PRODUCER_SOCK_NAME中已列出的 socket 里选择不会引入新端点。host 启动traced_probesPERFETTO_PRODUCER_SOCK_NAME127.0.0.1:20001 sudo -E tracebox traced_probessudo -E保留环境变量以获取 ftrace 权限。guest 启动traced_relayPERFETTO_RELAY_SOCK_NAMEhost-ip:20001 tracebox traced_relay成功时输出形如Started traced_relay, listening on /tmp/perfetto-producer, forwarding to host-ip:20001的启动行。guest 启动traced_probes直接sudo tracebox traced_probes无环境变量时自动连接默认 UNIX socket即traced_relay监听的路径。host 侧用显式TraceConfig录制多机追踪要求显式配置tracebox perfetto -t 10s ...简写只会录 host 本机——配置中必须包含trace_all_machines: true或各数据源的machine_name_filter例如buffers { size_kb: 32768 fill_policy: RING_BUFFER } trace_all_machines: true data_sources { config { name: linux.ftrace ftrace_config { ftrace_events: sched/sched_switch } } } duration_ms: 10000随后执行tracebox perfetto --txt -c config.pbtx -o trace.pftrace。验证两台机器都在 trace 中在 SQL 查询视图中执行SELECT id, raw_id, sysname, release, arch, num_cpus FROM machine;期望两行id 0恒为 host再通过cpu表 join 按机器统计事件数SELECT cpu.machine_id, COUNT(*) AS num_events FROM ftrace_event JOIN cpu USING (ucpu) GROUP BY cpu.machine_id;常见故障排查要点machine表只有一行通常是连通性问题检查端口可达、防火墙、host 是否绑定了0.0.0.0而非127.0.0.1traced_relay立即退出并打印用法说明PERFETTO_RELAY_SOCK_NAME未设置。总结与下一步多机追踪架构的核心设计哲学可以概括为让一台 host 承担全部状态buffer、consumer、配置让远程机器只做轻薄的 IPC 转发与时钟测量再通过SetPeerIdentity建立机器身份、通过 ping 协议把跨内核时钟偏移折叠进既有的时钟图最终在 Trace Processor 侧得到一张带machine_id维度的统一时间轴。这与 trace-processor-architecture 中导入期统一时钟图的设计一脉相承。后续深入方向Multi-machine recording——两台 Linux 主机录制多机 trace 的完整逐步演练Trace merging——事后把独立录制的 trace 合并进同一多机模型Clock Synchronization——跨机偏移在导入时折叠进的单机时钟同步图machine表参考——由SetPeerIdentity填充的表完整 schema。【免费下载链接】perfettoProduction-grade client-side tracing, profiling, and analysis for complex software systems.项目地址: https://gitcode.com/GitHub_Trending/pe/perfetto创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表