背景信息
我们有一台Dell R620电信企业应用服务器,运行在RHEL 5平台上,并部署了Apache Web服务器和OCCAS应用服务器。我们有专有的电话作为客户端连接到应用服务器,并使用Apache处理所有基于HTTP的请求。Apache服务器被配置为代理/转发请求到OCCAS。
问题
专有的电话会在启动时发送大约350个HTTP请求,在35秒内即每秒发送大约10个请求。我们可以清楚地看到电话与Apache之间的连接正在重用,而Apache与OCCAS之间的连接没有重用连接,导致每个请求创建一个新的连接。Apache与OCCAS之间的连接被Apache /代理关闭(我们从代理看到FIN),服务请求后就关闭了。因此,在所有350个请求都得到服务后,在一分钟内我们可以看到350个处于TIME_WAIT状态的套接字。我们的系统应该可以处理500个这样的电话。现在,如果您能想象当所有500个电话同时做出350个请求时,将需要175,000(350 * 500)个临时端口!因此,我试图使Apache代理与OCCAS之间的连接重用起来,但遇到了问题。
我已经发布了我们拥有的配置以及我们尝试并失败的不同方法,以使连接重用起作用。
我们的配置
1)我们系统中/etc/httpd/conf/httpd.conf 中配置的prefork和worker MPM如下所示,并且我们正在使用默认的prefork MPM。
<IfModule prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 256
MaxClients 256
MaxRequestsPerChild 4000
</IfModule>
<IfModule worker.c>
StartServers 8
MaxClients 150
MinSpareThreads 5
MaxSpareThreads 20
ThreadsPerChild 256
MaxRequestsPerChild 4000
</IfModule>
2)/etc/httpd/conf/httpd.conf中与Keepalive相关的参数如下:
[root@host ~]# grep -i keepalive /etc/httpd/conf/httpd.conf | grep -v "#"
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
[root@host ~]#
3) 代理配置如下:
<VirtualHost *:80>
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location /ds-webservice>
ProxyPass http://{IP address of local host}:8001/ds-webservice retry=0
ProxyPassReverse http://{IP address of local host}:8001/ds-webservice
</Location>
.
.
# Few more similar ProxyPass
.
.
</VirtualHost>
4) 我们使用默认的prefork Apache:
[root@host ~]# httpd -l
Compiled in modules:
core.c
prefork.c
http_core.c
mod_so.c
尝试但未能实现连接重用的测试
测试1) 我们注意到mod_proxy在转发请求时发送了“Connection: Keep-alive”标头(但没有发送“Keep-alive”标头本身),而OCCAS没有响应“Connection”或“Keep-alive”标头。我们最初怀疑Apache不喜欢在缺少这些标头的情况下的响应。因此,作为一个实验,我们将请求转发到另一个Apache中,在那里我们确实从其他Apache收到了响应的“Connection”或“Keep-alive”标头,但mod_proxy仍然没有进行连接重用。因此,我们确认是mod_proxy存在问题(或者可能是我们方面的某些错误配置)。
测试2) 经过一些研究,我们发现了一个关于2.2.0中使用prefork进行连接重用的错误报告-https://issues.apache.org/bugzilla/show_bug.cgi?id=38602。错误38602已在2.2.1中修复。然而,根据Can I use Apache mod_proxy as a connection pool, under the Prefork MPM?的帖子,我们发现即使升级后问题似乎仍然存在。因此,为了确保,我们将Apache从2.2.3升级到2.2.26,但mod_proxy仍未进行连接重用。
测试3) 我们尝试使用不同的ProxyPass参数进行了几次测试(在httpd.conf中没有更改任何内容),但没有一个有帮助,即mod_proxy没有进行连接重用:
注意:除(7)之外,我们在测试中在“ProxyPass http://{本地主机的IP地址}:8001/ds-webservice”旁添加了以下参数。
1. retry=0 (我们的默认配置)
2. disablereuse=OFF
3. max=256 retry=0
4. proxyto=80
5. retry=0 keepalive=ON
6. retry=300 smax=5 max=20 ttl=120
7. 最后,我们在代理配置中添加了特定于keep-alive的参数,希望它会覆盖http.conf中的keep-alive参数:
<VirtualHost *:80>
Timeout 300
KeepAlive On
MaxKeepAliveRequests 1000
KeepAliveTimeout 100
ProxyRequests Off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location /ds-webservice>
ProxyPass http://{IP address of local host}:8001/ds-webservice retry=0
ProxyPassReverse http://{IP address of local host}:8001/ds-webservice
</Location>
.
.
# Few more similar ProxyPass
.
.
</VirtualHost>
根据 Can I use Apache mod_proxy as a connection pool, under the Prefork MPM? 这篇文章,我们在2.2.26上通过使用httpd.worker从prefork Apache切换到worker Apache,但mod_proxy没有进行连接复用。
看起来我们在这里缺少了一些非常基本的东西。如果ProxyPass或prefork配置有任何问题,请指点一下我们吧,因为它们都是相关的。任何指针都将非常有帮助。
提前感谢你!
敬礼 Goutham Prasad