![有些 Apache 请求很慢,大多数请求可以立即完成](https://linux22.com/image/556503/%E6%9C%89%E4%BA%9B%20Apache%20%E8%AF%B7%E6%B1%82%E5%BE%88%E6%85%A2%EF%BC%8C%E5%A4%A7%E5%A4%9A%E6%95%B0%E8%AF%B7%E6%B1%82%E5%8F%AF%E4%BB%A5%E7%AB%8B%E5%8D%B3%E5%AE%8C%E6%88%90.png)
我有两台 Dell R410 Web 服务器(2 个四核 Xeon E5520,8GB 内存),运行 Debian 5 稳定版。它们的补丁已经被忽视了一段时间,所以最近我们进行了一次补丁运行,以使所有内容保持最新状态 - 这是因为它运行的应用程序的新版本需要 PHP 5.3.6。内核没有更新,因为它来自 Debian backports 存储库(安装的版本是 2.6.30-bpo.1-amd64)。
自补丁发布以来,用户一直抱怨网站速度太慢。大多数请求都能立即得到处理,但偶尔也会在某个请求上“卡住”。卡住的请求似乎没有任何明显的规律。
这些服务器位于负载平衡器后面,它们同时更新,并且在运行修补程序时都开始出现此问题。它们当时没有重新启动,但此后一直没有效果。
我在服务器上设置了一个脚本来循环time curl localhost:80/alive
,其中有一个简单的 index.html 文件,只包含“OK”。奇怪的是,这些请求仍然会延迟,延迟频率和持续时间与实际 php 内容的请求相同。常见的时间是 3 秒、9 秒、25 秒、45 秒,有些甚至超过 3 分钟。45 秒是常见的响应时间,但浏览器当然会在此之前放弃,因此实际上没有响应。
Apache 工作进程配置如下:
<IfModule mpm_prefork_module>
StartServers 50
MinSpareServers 10
MaxSpareServers 150
ServerLimit 500
MaxClients 500
MaxRequestsPerChild 5000
</IfModule>
对于拥有 8GB 内存的服务器来说,这似乎是合理的。实际上,工作线程数量很少超过 170,因此我们不会达到该限制,而且有足够的可用内存。平均负载较低,徘徊在 0.5-1.5 左右
内核是一个旧的反向移植,所以我尝试将其更新到 lenny 的最新反向移植(2.6.32-bpo.5-amd64),但它在启动时出现故障,我不得不让我们的主机用旧版本重新启动它,所以在我们尝试更新它们的 bios 并用 Debian 6 格式化它们之前,我想探索其他选项。
Apache 似乎是罪魁祸首,因此下一步是更新到最新的 apache 反向移植,但版本从 2.2.9-10+lenny4 到 2.2.9-10+lenny9 只是一个小变化,所以我没想到会有任何重大变化。
安装了 PHP,版本 5.3.6,来自 dotdeb。以前的版本是 5.3.0 自定义编译。此外,我的老板刚刚告诉我,通过 https 的请求不会延迟,但我自己还没有确认这一点。
# apache2 -V
Server version: Apache/2.2.9 (Debian)
Server built: Dec 11 2010 21:34:00
Server's Module Magic Number: 20051115:15
Server loaded: APR 1.2.12, APR-Util 1.2.12
Compiled using: APR 1.2.12, APR-Util 1.2.12
Architecture: 64-bit
Server MPM: Prefork
threaded: no
forked: yes (variable process count)
Server compiled with....
-D APACHE_MPM_DIR="server/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=128
-D HTTPD_ROOT=""
-D SUEXEC_BIN="/usr/lib/apache2/suexec"
-D DEFAULT_PIDLOG="/var/run/apache2.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_LOCKFILE="/var/run/apache2/accept.lock"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="/etc/apache2/mime.types"
-D SERVER_CONFIG_FILE="/etc/apache2/apache2.conf"
# apache2ctl -t -D DUMP_MODULES
Loaded Modules:
core_module (static)
log_config_module (static)
logio_module (static)
mpm_prefork_module (static)
http_module (static)
so_module (static)
alias_module (shared)
auth_basic_module (shared)
authn_file_module (shared)
authz_default_module (shared)
authz_groupfile_module (shared)
authz_host_module (shared)
authz_user_module (shared)
autoindex_module (shared)
cgi_module (shared)
deflate_module (shared)
dir_module (shared)
env_module (shared)
geoip_module (shared)
mime_module (shared)
negotiation_module (shared)
php5_module (shared)
rewrite_module (shared)
setenvif_module (shared)
ssl_module (shared)
status_module (shared)
Syntax OK
非常感谢您的帮助!
答案1
我已经为此苦苦挣扎了一个星期了,现在我的老板已经解决了。
当我们查看日志中的 Apache 响应时间时,我们发现它响应很快 - 延迟甚至在请求到达 Apache 之前就发生了。因此,他查看了 tcp 堆栈设置,并将其与运行 Red Hat 5.6 的另一台服务器进行比较。
长话短说,启用 tcp syn cookies(net.ipv4.tcp_syncookies=1
在 /etc/sysctl.conf 中)已解决问题。此设置旨在防止 SYN 洪水,显然确实允许更快的响应。我们可能意外(或故意)被洪水淹没。
更多信息请参见此链接,所描述的症状正是我们所看到的:http://baheyeldin.com/technology/linux/detecting-and-preventing-syn-flood-attacks-web-servers-running-linux.html
我当时正在看netstat -alnt
,发现绝大多数连接都处于 TIME_WAIT 状态,而不是 SYN_RECV(也许 -l 选项没有显示半开连接)。
然而我们现在经常在 dmesg 中看到这种情况:
possible SYN flooding on port 80. Sending cookies.
我应该做更多的挖掘。