起首,我测验测验了node_exporter的其他一些版本,并启用或禁用了不合的参数,但并没有什么效不雅。我还测验测验在strace下运行实例,似乎没有产生崩溃,这强烈说清楚明了这是在竞争前提下的一个问题。strace平日会拦截所有线程运行的所有体系调用,并在某种程度上让应用法度榜样的履行串行化。后来,我发明strace也崩溃了,然则运行了很长时光才出现崩溃。因为这似乎与并发有关,所以我试着设置GOMAXPROCS=1,这个参数告诉Go只应用一个OS级其余线程来运行Go代码。崩溃再也没有产生,问题再一次指向了并发。
到今朝为止,我已经收集了必定命量的崩溃日记,并开端存眷个中的一些规律。固然崩溃的地位以及外面原因有很多种,然则最终的缺点信息可以分为多个不合的类型,并且每种类型的缺点不止出现过一次。所以我开端应用谷歌搜刮这些缺点,并有时光发清楚明了 Go issue #20427 。固然这个问题似乎与Go无关,但却引起了类似的段缺点和随机性问题。在Go 1.9之后,这个问题被封闭了,但并没有获得解决。没有人知道根来源基本因是什么,并且它再也没有出现过。
所以,我大年夜issue中抓取了 这段 声称可以或许重现问题的示例代码,并在我的机械上运行。你看,它在几秒钟内崩溃了。太好了。这比等待node_exporter崩溃所需的时光要短得多。
这并没有让我大年夜Go的角度更接近这个问题,但它却加快了我测试的速度。所以,我们来尝尝大年夜另一个角度进行分析吧。
把不合的电脑区分开来
这个问题产生在我的标记本电脑上,但在其他机械上却都没有产生。我测验测验着在其他电脑上重现这个问题,但没有一台机械产生崩溃。这解释我的标记本电脑中有一些特其余器械。因为Go是静态链接的二进制文件,所以其余的用户空间并不重要。这留下了两个相干的部分:硬件和内核。
内核的vDSO实际上并不算是内核代码。 vDSO是内核放置在每个过程地址空间中的一个小型共享库,它许可应用法度榜样在不分开用户模式的情况下履行特定的体系调用。这大年夜大年夜进步了体系机能,同时仍然许可内核根据须要更改┞封些体系调用的实现细节。
我没有什么办法来测试各台电脑的硬件,除了我本身的机械,但我可以捣鼓内核。所以,我们来试着走第一步:它会在虚拟机中崩溃吗?
为了测试这个,我创建了一个最小化的initramfs,这使我可以或许快速启动QEMU虚拟机,而不必安装发行版或启动完全的Linux体系。我的initramfs是用Linux的scripts/gen_initramfs_list.sh构建的,包含以下文件:
dir /dev 755 0 0nod /dev/console 0600 0 0 c 5 1nod /dev/null 0666 0 0 c 1 3dir /bin 755 0 0file /bin/busybox busybox 755 0 0slink /bin/sh busybox 755 0 0slink /bin/true busybox 755 0 0file /init init.sh 755 0 0file /reproducer reproducer 755 0 0
/init是Linux initramfs的人口,在我这个案例中是一个简单的shell脚本,用于启动测试并测量时光:
#!/bin/shexport PATH=/binstart=$(busybox date +%s)echo "Starting test now..."/reproducerret=$?end=$(busybox date +%s)echo "Test exited with status $ret after $((end-start)) seconds"
arch/x86/entry/vdso/vclock_gettime.o.no_inline_opt: file format elf64-x86-64Disassembly of section .text:0000000000000000 <vread_tsc>: 0: 55 push %rbp 1: 48 89 e5 mov %rsp,%rbp 4: 90 nop 5: 90 nop 6: 90 nop 7: 0f 31 rdtsc 9: 48 c1 e2 20 shl $0x20,%rdx d: 48 09 d0 or %rdx,%rax 10: 48 8b 15 00 00 00 00 mov 0x0(%rip),%rdx # 17 <vread_tsc+0x17> 17: 48 39 c2 cmp %rax,%rdx 1a: 77 02 ja 1e <vread_tsc+0x1e> 1c: 5d pop %rbp 1d: c3 retq 1e: 48 89 d0 mov %rdx,%rax 21: 5d pop %rbp 22: c3 retq 23: 0f 1f 00 nopl (%rax) 26: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1) 2d: 00 00 00 0000000000000030 <__vdso_clock_gettime>: 30: 55 push %rbp 31: 48 89 e5 mov %rsp,%rbp 34: 48 81 ec 20 10 00 00 sub $0x1020,%rsp 3b: 48 83 0c 24 00 orq $0x0,(%rsp) 40: 48 81 c4 20 10 00 00 add $0x1020,%rsp 47: 4c 8d 0d 00 00 00 00 lea 0x0(%rip),%r9 # 4e <__vdso_clock_gettime+0x1e> 4e: 83 ff 01 cmp $0x1,%edi 51: 74 66 je b9 <__vdso_clock_gettime+0x89> 53: 0f 8e dc 00 00 00 jle 135 <__vdso_clock_gettime+0x105> 59: 83 ff 05 cmp $0x5,%edi 5c: 74 34 je 92 <__vdso_clock_gettime+0x62> 5e: 83 ff 06 cmp $0x6,%edi 61: 0f 85 c2 00 00 00 jne 129 <__vdso_clock_gettime+0xf9>[...]
/bin/busybox是BusyBox的一个静态链接版本,平日用于如许的最小化体系,用以供给所有根本的Linux shell实用法度榜样(包含shell本身)。
initramfs可以如许构建(大年夜Linux内核源代码树中),个中,list.txt是膳绫擎的文件列表:
scripts/gen_initramfs_list.sh -o initramfs.gz list.txt
唉,这弗成能成为node_exporter崩溃的原因。那个应用法度榜样应用的RAM很少,所以它碰着坏位的机会是异常低的。这类问题一般表示抱病不会很明显,也许会导致某些图形中的像素缺点、在某些文本中出现单个字母的翻转、也可能指令被破坏导致无法运行,或者当某些异常重要的数据确切落在了坏位上会出现崩溃。尽管如斯,它确切会导致经久的靠得住性问题,这就是办事器和其他靠得住设备必须应用ECC RAM才能改┞俘这种缺点的原因。
推荐阅读
NVIDIA Titan V显卡拆解:211亿晶体管堆出巨型怪物
NVIDIA近日忽然宣布了第一款基于下代12nm Volta架构核心的显卡Titan V(此前的Tesla V100是计算卡),轻轻松松成为地球上最强大年夜的显卡。Titan V基于最高规格的GV100核心,集成211亿个晶>>>详细阅读
本文标题:Go运行时,对bug的分析调试过程解析
地址:http://www.17bianji.com/lsqh/39892.html
1/2 1