我们有一个 Tomcat 前端服务器,它代理我们的 Apache 2.2.11 应用服务器,在 64 位 Fedora 2.6.21.7 EC2 2xlarge 实例 (AKI aki-b51cf9dc) 上运行。Apache 正在运行 mod_perl 并且没有线程化。
我们试图让在另一个 EC2 实例上运行的 Tomcat 和 Apache 服务器之间的连接保持很长时间,而不是保持来自外部客户端直接进入 Apache 服务器的连接。我们的配置如下所示:
Listen 80
NameVirtualHost *:80
# used for external clients
<VirtualHost *:80>
ServerName xxx.yyy.com
ServerAlias *.yyy.com
DocumentRoot "/var/www/html"
KeepAlive Off
</VirtualHost>
# used from tomcat server on local network
<VirtualHost *:80>
ServerName ip-<Apache-server-local-IP>.ec2.internal
KeepAlive On
KeepAliveTimeout 3600
MaxKeepAliveRequests 0
DocumentRoot "/var/www/html"
</VirtualHost>
TimeOut 60
MinSpareServers 20
MaxSpareServers 30
StartServers 20
MaxClients 60
GracefulShutdownTimeout 90
我们已经尝试了 MaxKeepAliveRequests 和 KeepAliveTimeout 的各种值,服务器肯定会与 Tomcat 保持一段时间的连接,但它总是在几秒钟内关闭它,当时只处理了几十个请求。可能很重要的是,我从未见过一个进程在使用 mod_status 观察时在套接字上维护 100 个或更多连接。
与非 Tomcat 客户端永远不会有任何持久连接,因此我们知道那里存在一些差异,并且在这两种情况下肯定都应用了 VirtualHost 配置。
我应该提到,来自 Tomcat 的请求都是 POST,而其他请求是 POST 和 GET 的混合。
当我使用 tcpdump 查看给定端口上的流量时,我可以清楚地看到许多 POST 正在正确处理,然后在返回一个好的回复(200,数据看起来不错)后的某个时刻,Apache 服务器立即关闭连接,发送一个FIN 到 Tomcat。这种情况发生在最后一个请求和倒数第二个请求或回复之间绝对没有区别的情况下,除了像真实客户端的 IP 这样的次要数据之外,因此在处理请求时没有迹象表明服务器在呕吐。当然,错误日志中没有任何可疑之处,而且 httpd 进程本身也没有死。
从 netstat 我们可以看到与 Tomcat 服务器的连接保持打开状态几秒钟,但在远程端口范围内快速循环,验证了我们在其他地方看到的情况。这几乎就像 Apache 试图公平分配连接以防止持久连接使其他连接挨饿——但它不会那样做,不是吗?!
我只想被告知我们在这里做了一些愚蠢的事情!拜托,请告诉我我是个白痴,或者至少是近视...