共计 1505 个字符,预计需要花费 4 分钟才能阅读完成。
https://www.bilibili.com/vide…
背景
零碎调用是内核提供给用户的性能接口,在咱们的零碎中,通常会运行许多零碎调用,其中有很多零碎调用是由咱们的用户程序来触发的 (比方 C 语言中的 printf() 函数,理论会触发底层的 write()零碎调用)。在绝大多数状况下,零碎调用能够在很短的工夫内执行实现并且返回,然而在某些状况下,零碎调用可能会执行的比较慢,从而成为咱们过程运行时的瓶颈。
对于这些执行较慢的零碎调用咱们能够分为两类,一类是在肯定工夫内执行实现,然而执行工夫过长的零碎调用,咱们能够称之为慢零碎调用;另一类是在肯定工夫内始终未返回的零碎调用,咱们称之为超时零碎调用。在 Kindling 中,咱们实现了对于这两类零碎调用的捕捉和剖析,并将其报告给下层用户,以便用户洞察零碎调用的状况。
实现原理
内核空间 eBPF 捕捉零碎调用
首先,咱们能够应用 eBPF 技术通过内核提供的 rawsyscalls 目录下的 tracepoint 来捕捉所有零碎调用的入口和进口 (sysenter 对应零碎调用的入口,sysexit 对应零碎调用的进口),可在/sys/kernel/debug/tracing/events/rawsyscalls/
中看到该 tracepoint 的具体信息。
图 1 sys_enter tracepoint 的 format 信息
咱们通过该 tracepoint 捕捉所有零碎调用,并将每一个零碎调用关联到具体的线程上,发送至用户空间进行进一步解决。
用户空间关联系统调用工夫信息
慢零碎调用
对于一个零碎调用而言,它有一个 enter 和一个 exit(所有零碎调用都只有一个 trap,不会呈现堆栈序列的 enter 和 exit),咱们能够在零碎调用 enter 时获取以后工夫戳,而后在 exit 时再获取以后工夫戳,此时两个工夫戳的差值就是该零碎调用的理论执行时长,在 Kindling 中,咱们将该值称为一个慢零碎调用的 latency。
图 2 慢零碎调用实现示意
超时零碎调用
对于超时的零碎调用,它们在一段时间范畴内并未返回,因而咱们无奈获取到零碎调用的 exit 信息,目前 kindling 采取的策略是保护一个以 tid 为 key,syscall 信息为 value 的 map,当有零碎调用进入时,在 map 做一次标记,而后咱们会定时去扫描这个 map,如果发现 map 中有超时的零碎调用则立刻将该零碎调用标记为超时零碎调用。
图 3 超时零碎调用实现示意
demo 测试
这里咱们写一个简略的 demo 来测试一下咱们所捕捉到的慢零碎调用,咱们写一个最简略的调用 nanosleep()零碎调用的例子,让过程睡眠 3 秒钟,咱们能够在运行的 Kindling 输入日志中看到捕捉到的信息:
咱们能够看到,Kindling 捕捉到了该零碎调用,并给出了其类型,执行时长以及 TID、PID 等具体信息。
总结
首先,咱们通过 eBPF 技术和内核提供的零碎调用 tracepoint 捕捉了所有的零碎调用数据,而后把零碎调用与线程信息做了关联,而后咱们在用户空间对系统调用的 enter 和 exit 进行了 latency 的计算以判断是否为慢零碎调用,特地的是,对于那些超时的零碎调用,咱们无奈间接计算 latency,采取了应用 map 标记零碎调用入口并定时扫描 map 的策略,从而实现对于超时零碎调用的捕捉。Kindling 是一款基于 eBPF 的云原生可观测性开源工具,旨在帮忙用户更好更快的定界云原生零碎问题,并致力于打造云原生全故障域的定界能力。
Kindling 是一款基于 eBPF 的云原生可观测性开源工具,旨在帮忙用户更好更快的定界云原生零碎问题,并致力于打造云原生全故障域的定界能力。
关注咱们
退出咱们