#BPF
BPF LRU_HASH_MAP 及 HASH_MAP 的使用异常
BPF 技术看起来还有很多不易察觉的缺陷。最近又踩了一个坑。记录下。
LRU_HASH_MAP 在实现的时候,出现了不符合预期的数据驱逐问题:设定一个 512 大小的LRU_HASH_MAP,很可能出现在40-50个key的时候,之前的key就被覆盖。在一段时间未更新时,重新更新也可能会出现异常。总结就是,执行了写入操作,很可能没有写入。这个问题在Elements incorrectly evicted from eBPF LRU hash map有较为详细的描述。
TCP close 过程分析
最近做了一些 TCP 连接观测相关的项目,又到了一个节奏点上了。这里趁着这个机会,做一些总结,同时描述一下 tcp close 过程中的一些疑惑。
在一些场景下,对服务的调用观测是很有价值的。笔者最近实践了使用tcp_close对服务主被调信息的观测,在这里作一下记录。
如何追踪golang channel?
2023年就要结束了,算起来距离上一次更新也有很久了。搜肠刮肚,总得在23年结束前再搞两篇总结,算是有始有终。总结今年,总还是绕不过 BPF,golang。既然如此,就对BPF观测golang这个话题再往下挖掘下,先做第一篇文章。下旬如果有时间并且顺利的话,希望能把BPF的原理总结完成。
在无侵入观测服务拓扑四元组的一种实现中,笔者有提到追踪golang处理过程的两个无法解决的问题是golang里的channel处理以及goroutine pool。再深究下,这两个问题实际上都可以归纳到对channel的处理,因为很多goroutine pool都离不了channel的使用,比如Jeffail/tunny这个库。
本文将会构建一个channel的追踪的方案。
BPF追踪Go程序的挑战
原文地址Challenges of BPF Tracing Go。翻译不尽如人意,继续努力。
BPF追踪Go程序的挑战
当大家对Go 1.17语言调用规约(function calling convention)调整带来的性能优化感到兴奋时,我却遗憾的看到Go 1.17并没有让BPF uretprobe变得可行。事实证明,我还没有完全意识到Go的可调整的栈空间会让事情变得多复杂。
go-1.17+ 调用规约
go-1.17是一个很不友好的版本,这里我指的是函数调用规约的变更。在此之前,虽然栈传参比较奇怪,但是在掌握了规律后,参数信息很好获取。升级到go-1.17之后,笔者发现变更后的寄存器传值方式并不是系统的调用规约,至少和C/C++的是完全不一致的。这个问题使得笔者在处理ebpf方案时,始终无法覆盖go-1.17+的版本。虽然短期不会造成影响,线上服务使用的大多还在go-1.16以下,但是这始终是一个绕不过去的问题。近期通过查阅资料和参考其他开源项目里对这部分内容的处理,整理了一下go-1.17+的调用规约。
go在1.17之前使用的是内存栈来传递参数,这种传参的方式使得golang的语言设计很灵活:golang函数的多返回值能够很容易的实现。同样的,由于golang需要这样灵活的能力,是的系统默认的调用规约方式并不适用。在Proposal: Register-based Go calling convention文章里对这个问题进行了详细的讨论,总结起来是golang的特性使得使用系统默认规约并不能带来多语言交互上的收益,且golang希望保持独特。
本文下面会给出总结的调用规约,并且给出验证程序。本文档的整理所基于的平台是x86_64的centos8系统。其他架构下,寄存器名称可能不同。