我正在尝试找出运行非常缓慢的 wordpress 网站的原因:在请求页面时,它会挂起大约 20 秒,然后页面才开始加载。
我尝试了常用的方法:WP 调试模式、检查慢速 MySQL 查询、禁用插件、检查 Apache 是否未排队请求等,但都没有成功。现在,我只能使用 strace 观察 Apache 进程(我以 mod_php 的形式运行 PHP),试图查看发生了什么。不幸的是,我的 kernel-fu 很弱,我需要一些帮助来解释 strace 输出。
我正在使用 -r 运行 strace,如果我正确理解了手册页,这将指示前一个系统调用所花费的时间。
查看输出,我发现一些调用需要 5 秒,例如:
0.000114 accept4(4, {sa_family=AF_INET6, sin6_port=htons(46242), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28], SOCK_CLOEXEC) = 13
0.000116 getsockname(13, {sa_family=AF_INET6, sin6_port=htons(80), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
0.000109 fcntl(13, F_GETFL) = 0x2 (flags O_RDWR)
0.000061 fcntl(13, F_SETFL, O_RDWR|O_NONBLOCK) = 0
0.000078 read(13, "GET /wp-content/uploads/fake-ici"..., 8000) = 593
0.000144 stat("/var/www/wp-content/uploads/fake-icicles-500x500.jpg", {st_mode=S_IFREG|0777, st_size=34241, ...}) = 0
0.000197 open("/var/www/wp-content/uploads/fake-icicles-500x500.jpg", O_RDONLY|O_CLOEXEC) = 14
0.000100 close(14) = 0
0.000097 read(13, 0x7f66f397b048, 8000) = -1 EAGAIN (Resource temporarily unavailable)
0.000079 writev(13, [{"HTTP/1.1 304 Not Modified\r\nDate:"..., 182}], 1) = 182
0.000161 write(8, "127.0.0.1 - - [26/Oct/2016:14:17"..., 235) = 235
0.000112 times({tms_utime=3107, tms_stime=70, tms_cutime=0, tms_cstime=0}) = 1802798719
0.000090 poll([{fd=13, events=POLLIN}], 1, 5000) = 0 (Timeout)
5.005144 shutdown(13, SHUT_WR) = 0
0.000130 poll([{fd=13, events=POLLIN}], 1, 2000) = 1 ([{fd=13, revents=POLLIN|POLLHUP}])
1.000750 read(13, "", 512) = 0
我的解释是,轮询 ID 为 13 的文件描述符需要 5 秒,并且已超时(倒数第 4 行)。13 看起来像是已打开用于将 HTTP 响应写回客户端的套接字的 ID。这是正确的吗?我还能从上面学到什么吗?我是否应该担心输出中途 read() 上的“资源暂时不可用”?
答案1
是的,你的解释是正确的。
实际上,据我了解,您看到的是 HTTP KeepAlive。
会发生什么:
您收到一个连接并接受它,文件描述符= 13:
0.000114 accept4(4, {sa_family=AF_INET6, sin6_port=htons(46242), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28], SOCK_CLOEXEC) = 13
您收到一个 HTTP GET 请求:
0.000078 read(13, "GET /wp-content/uploads/fake-ici"..., 8000) = 593
您编写响应,在本例中为 304“未修改”,而不是整个文件,因为请求是条件 GET,可能是由于 If-Modified-Since,因为我没有看到对打开的文件的读取,但不确定):
0.000079 writev(13, [{"HTTP/1.1 304 Not Modified\r\nDate:"..., 182}], 1) = 182
您向日志文件写入一个条目:
0.000161 write(8, "127.0.0.1 - - [26/Oct/2016:14:17"..., 235) = 235
然后,由于 KeepAlive,您将等待对同一套接字的另一个请求,Apache 中的默认值为 5 秒:
0.000090 poll([{fd=13, events=POLLIN}], 1, 5000) = 0 (Timeout)
在保持活动间隔期间没有其他请求到达,因此您开始关闭 TCP 连接:
5.005144 shutdown(13, SHUT_WR) = 0
至于读取返回 -EAGAIN(资源暂时不可用)这是正常的,请查看此处以获得比我的更好的描述:https://stackoverflow.com/questions/10318191/reading-socket-eagain-resource-temporarily-unavailable#10318268