Apache Tomcat 在 300 个连接后窒息

joh*_*tus 16 tomcat performance-tuning tcp apache-2.2

我们在 EC2 上托管的 Tomcat 前面有一个 apache 网络服务器,实例类型特大,内存为 34GB。

我们的应用程序处理大量外部网络服务,我们有一个非常糟糕的外部网络服务,在高峰时段需要将近 300 秒来响应请求。

在高峰时段,服务器只有大约 300 个 httpd 进程而窒息。ps -ef | grep httpd | wc -l =300

我在谷歌上搜索并发现了许多建议,但似乎没有任何效果..以下是我所做的一些配置,这些配置直接取自在线资源。

我在 apache 和 tomcat 中都增加了最大连接数和最大客户端数的限制。这是配置详细信息:

//阿帕奇

   <IfModule prefork.c>
    StartServers 100
    MinSpareServers 10
    MaxSpareServers 10
    ServerLimit 50000
    MaxClients 50000
    MaxRequestsPerChild 2000
    </IfModule>
Run Code Online (Sandbox Code Playgroud)

//tomcat

    <Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
           connectionTimeout="600000"
           redirectPort="8443"
           enableLookups="false" maxThreads="1500"
           compressableMimeType="text/html,text/xml,text/plain,text/css,application/x-javascript,text/vnd.wap.wml,text/vnd.wap.wmlscript,application/xhtml+xml,application/xml-dtd,application/xslt+xml"
           compression="on"/>
Run Code Online (Sandbox Code Playgroud)

//sysctl.conf

 net.ipv4.tcp_tw_reuse=1
 net.ipv4.tcp_tw_recycle=1
 fs.file-max = 5049800
 vm.min_free_kbytes = 204800
 vm.page-cluster = 20
 vm.swappiness = 90
 net.ipv4.tcp_rfc1337=1
 net.ipv4.tcp_max_orphans = 65536
 net.ipv4.ip_local_port_range = 5000 65000
 net.core.somaxconn = 1024
Run Code Online (Sandbox Code Playgroud)

我一直在尝试许多建议,但徒劳无功......如何解决这个问题?我确定 m2xlarge 服务器应该提供超过 300 个的请求,可能我的配置可能出错了..

服务器仅在高峰时段和有 300 个并发请求等待 [300 秒延迟] web 服务响应时阻塞。

我只是用 netstat 监视 tcp 连接

我发现大约 1000 个连接处于 TIME_WAIT 状态,不知道这对性能意味着什么,我确定它一定会增加问题。

TOP的输出

 8902  root      25   0 19.6g 3.0g  12m S  3.3  8.8  13:35.77 java
 24907 membase   25   0  753m 634m 2528 S  2.7  1.8 285:18.88 beam.smp
 24999 membase   15   0  266m 121m 3160 S  0.7  0.3  51:30.37 memcached
 27578 apache    15   0  230m 6300 1536 S  0.7  0.0   0:00.03 httpd
 28551 root      15   0 11124 1492  892 R  0.3  0.0   0:00.25 top


 Output of free -m
 total       used       free     shared    buffers    cached
 35007       8470       26536    0          1         61
 8407        26599
 15999       15         15984

 output of iostat
 avg-cpu:  %user   %nice %system %iowait  %steal   %idle
      26.21    0.00    0.48    0.13    0.02   73.15

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda1             14.36         4.77       329.37    9005402  622367592
sdb               0.00         0.00         0.00       1210         48
Run Code Online (Sandbox Code Playgroud)

同样在高峰时间有大约 10-15k tcp 连接到 membase 服务器[本地]

MODJK 日志中的一些错误,我希望这能对这个问题有所了解。

[Wed Jul 11 14:39:10.853 2012] [8365:46912560456400] [error]         ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:18.627 2012] [8322:46912560456400] [error] ajp_send_request::jk_ajp_common.c (1630): (tom2) connecting to backend failed. Tomcat is probably not started or is listening on the wrong port (errno=110)
[Wed Jul 11 14:39:21.358 2012] [8351:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
[Wed Jul 11 14:39:22.640 2012] [8348:46912560456400] [error] ajp_get_reply::jk_ajp_common.c (2118): (tom1) Tomcat is down or refused connection. No response has been sent to the client (yet)
Run Code Online (Sandbox Code Playgroud)

~

Worker.properties
workers.tomcat_home=/usr/local/tomcat/
worker.list=loadbalancer
worker.tom1.port=8009
worker.tom1.host=localhost
worker.tom1.type=ajp13
worker.tom1.socket_keepalive=True
worker.tom1.connection_pool_timeout=600
worker.tom2.port=8109
worker.tom2.host=localhost
worker.tom2.type=ajp13
worker.tom2.socket_keepalive=True
worker.tom2.connection_pool_timeout=600
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tom1,tom2
worker.loadbalancer.sticky_session=True
worker.tom1.lbfactor=1
worker.tom1.socket_timeout=600
worker.tom2.lbfactor=1
worker.tom2.socket_timeout=600
Run Code Online (Sandbox Code Playgroud)

//解决了

感谢大家的宝贵建议。我错过了 AJP 1.3 连接器的 maxThreads 设置。现在一切似乎都在控制之中。

我也会开始研究像 nginx 这样的基于服务器的服务器。

HTT*_*500 13

您是否在端口 8009 上增加了 AJP 1.3 连接器中的 maxThreads?


Ale*_*lex 6

考虑像Apache一样nginxlighttpd在 Apache 之前设置一个异步代理 Web 服务器。Apache 同步提供内容,因此在客户端完整下载生成的内容之前,工作人员会被阻止(更多详细信息请点击此处)。设置异步(非阻塞)代理通常会显着改善情况(我曾经将同时运行的 Apache 工作人员的数量从 30 个降低到 3-5 个,nginx用作前端代理)。


Mat*_*Ife 5

我怀疑你的问题出在 tomcat 而不是 apache,从你显示的日志来看。当您尝试连接回 tomcat 时遇到“错误 110”,这表明您有一个等待服务的连接队列,这些连接队列不再适合 tomcat 中侦听套接字的侦听积压设置。

From the listen manpage:
   The  backlog  parameter defines the maximum length the queue of pending 
   connections may grow to.  If a connection request arrives with
   the queue full the client may receive an error with an indication
   of ECONNREFUSED or, if the underlying protocol supports  
   retransmission, the request may be ignored so that retries succeed.
Run Code Online (Sandbox Code Playgroud)

如果我不得不猜测,我会怀疑服务器“阻塞”时的绝大多数 HTTP 请求都被阻塞,等待某些东西从 tomcat 返回。我敢打赌,如果您试图获取一些由 apache 直接提供的静态内容(而不是代理到 tomcat),那么即使它通常“窒息”,这也会起作用。

不幸的是,我不熟悉 tomcat,但是有没有办法操纵它的并发设置呢?

哦,你可能还需要考虑其外部网络服务这就是限制连接该数量的可能性,是做给你降到300,所以它没有什么区别,你有多少并发的操纵做你的前侧如果实际上您建立的每个连接都依赖于外部 Web 服务响应。

在您提到的其中一条评论中,数据在 2 分钟后变得陈旧。我建议将您从此服务获得的响应缓存两分钟,以减少您驱动到外部 Web 服务的并发连接量。