前因
开发环境没问题的代码,在线上服务器运行总是会卡顿几分钟,即使代码里只有一句
<?php
echo 'hello cli' . PHP_EOL;
也会卡住,且这个卡顿非常奇怪,它并不是100%复现的,而是随机性的,随即做了N次追踪(因为他无法稳定复现
开始排查
最开始挺烦的,在挂追踪的时候总是会因为运行的不是特定文件导致追踪过长丢失记录.
所以说调试时候一定注意最好搞个专门的文件做测试,或者
嗯没有或者
首先
ps -aux | grep php
来找出你需要调试的进程的pid 如果是进程已经运行并卡住了的话
输出大概这样
root 21596 0.5 0.5 430188 19912 pts/4 S+ 22:29 0:00 php test.php
root 21598 0.0 0.0 112736 976 pts/1 S+ 22:29 0:00 grep --color=auto php
看到进程的pid为21596 执行
strace -yy -p 21596
获得输出
restart_syscall(<... resuming interrupted poll ...>) = 1
ioctl(3114.114.114.114:53]>, FIONREAD, [26]) = 0
recvfrom(3114.114.114.114:53]>, "\372\236\203\203\0\1\0\0\0\0\0\0\10host-name\0\0\34\0\1", 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("114.114.114.114")}, [16]) = 26
close(3114.114.114.114:53]>) = 0
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("114.114.114.114")}, 16) = 0
writev(3114.114.114.114:53]>, [{"\0\32", 2}, {"\322\221\1\0\0\1\0\0\0\0\0\0\10host-name\0\0\1\0\1", 26}, {"\0\32", 2}, {"\372\236\1\0\0\1\0\0\0\0\0\0\10host-name\0\0\34\0\1", 26}], 4) = 56
read(3114.114.114.114:53]>, 0x7fffc188e5b0, 2) = -1 ETIMEDOUT (Connection timed out)
close(3114.114.114.114:53]>) = 0
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("223.5.5.5")}, 16) = 0
writev(3223.5.5.5:53]>, [{"\0\32", 2}, {"\322\221\1\0\0\1\0\0\0\0\0\0\10host-name\0\0\1\0\1", 26}, {"\0\32", 2}, {"\372\236\1\0\0\1\0\0\0\0\0\0\10host-name\0\0\34\0\1", 26}], 4) = 56
read(3223.5.5.5:53]>, "\0e", 2) = 2
read(3223.5.5.5:53]>, "\322\221\201\203\0\1\0\0\0\1\0\0\10host-name\0\0\1\0\1\0\0\6\0\1\0"..., 101) = 101
read(3223.5.5.5:53]>, "\0e", 2) = 2
read(3223.5.5.5:53]>, "\372\236\201\203\0\1\0\0\0\1\0\0\10host-name\0\0\34\0\1\0\0\6\0\1\0"..., 101) = 101
close(3223.5.5.5:53]>) = 0
open("/usr/local/lib/libnss_myhostname.so.2", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
其他地方不重要所以我删除了,我们分析一下它干了什么
ioctl(3<UDP:[xxx.xxx.xxx.xxx:58453->114.114.114.114:53]>
udp 访问 114.114.114.114 的 53 端口recvfrom(3<UDP:[xxx.xxx.xxx.xxx:58453->114.114.114.114:53]>, "\372\236\203\203\0\1\0\0\0\0\0\0\10host-name\0\0\34\0\1", 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("114.114.114.114")}, [16]) = 26
发送数据包close(3<UDP:[xxx.xxx.xxx.xxx:58453->114.114.114.114:53]>) = 0
关闭read(3<TCP:[xxx.xxx.xxx.xxx:47930->114.114.114.114:53]>, 0x7fffc188e5b0, 2) = -1 ETIMEDOUT (Connection timed out)
重点 读取响应超时- 下面基本同理不讲了.
显然 知道原因了 众所周知 53是dns端口 114*4是电信(好像?)的dns服务器 它访问失败了或者请求解析超时了.
我们看一下包体
\372\236\203\203\0\1\0\0\0\0\0\0\10host-name\0\0\34\0\1
注意 host-name 是服务器的hostname 就是 [root@host-name ~]
很明显了,它去请求host-name 这个玩意dns服务器没有 自然不理他 于是它换个dns服务器继续请求 所以就在这卡了半天
修复
找到原因了自然就要修复,这个其实再做一个追踪就能看出来,大致信息如下
read(3, "127.0.0.1 localhost localhost."..., 4096) = 158
read(3, "", 4096) = 0
read(3,
在这里,它请求了hosts之后去调用dns了,因为libnss是负责dns的so
显然是因为hosts没有host-name
快速修复代码
echo "127.0.0.1 host-name" >> /etc/hosts
或
vim /etc/hosts
127.0.0.1 host-name
接下来跑一次测试,就会发现不再调用/usr/lib64/libnss_dns了
read(3, "127.0.0.1 localhost localhost."..., 4096) = 158
read(3, "", 4096) = 0
read(3, "# Configuration snippets may be "..., 4096) = 641
原因
尚不明确为什么一定会请求解析hosts 可能是我编译的php本身的问题? 等我
有空之后补充2333
暂无评论