我正在使用JBoss AS 4.2.3和seam框架。我的CPU使用率随着用户数量的增加而增加,仅80个用户就达到了99%。我们还使用Hibernate,EJB3和Apache与mod_jk进行负载均衡。
当我接受线程转储时,所有可运行的线程都使用以下跟踪执行相同的活动:
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.apache.coyote.ajp.AjpProcessor.read(AjpProcessor.java:1012)
at org.apache.coyote.ajp.AjpProcessor.readMessage(AjpProcessor.java:1091)
at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:384)
at org.apache.coyote.ajp.AjpProtocol$AjpConnectionHandler.process(AjpProtocol.java:366)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:446)
at java.lang.Thread.run(Thread.java:662)
我无法用堆栈跟踪来解释这一点。此外,我发现即使用户已注销,CPU利用率仍然与处于相同状态的线程相同。
答案 0 :(得分:1)
这些线程试图从Socket连接读取。在这种情况下,他们正在等待下一个请求从Apache中的mod_jk
发送到服务器。这很正常,它们可能不是您使用CPU的原因。
此时,您确实需要通过分析器运行应用程序。
如果你无法在系统上运行一个分析器(即它是一个生产盒),那么下一个最好的事情就是开始分别在几秒钟内进行多次堆栈转储,然后手动匹配线程标识。您需要查找运行代码的线程,并且似乎没有在转储之间进行更改。
这是一项非常繁琐的任务,并不总能得到明确的结果,但如果没有分析器或某种仪器,您将无法找到所有CPU的位置。
答案 1 :(得分:0)
按照https://developer.jboss.org/wiki/OptimalModjk12Configuration
中的说明,检查Apache和Jboss之间的AJP配置JBoss Web&#39>(Tomcat)server.xml AJP片段:
<Connector port="8009" address="${jboss.bind.address}" protocol="AJP/1.3" emptySessionPath="true" enableLookups="false" redirectPort="8443" ></Connector> Apache's httpd.conf: <IfModule prefork.c> StartServers 8 MinSpareServers 5 MaxSpareServers 20 ServerLimit 256 MaxClients 256 MaxRequestsPerChild 4000 </IfModule>
上述配置在加载时可能会导致mod_jk非常慢 并且没有响应,导致http错误,并导致半封闭 连接。出现这些问题是因为没有 指定用于处理孤立连接的连接超时,没有 在workers.properties中定义的错误处理属性,没有 Apache和Tomcat中设置的连接限制。
但是这个大量的线程可能来自另一个来源。如上所述here:
挂起Socket.read()的最常见情况是高 远程服务提供商的处理时间或不健康状态。 这意味着您需要与服务提供商进行通信 立即支持团队,以确认他们是否面临一些问题 他们的系统放缓状况。
您的应用服务器线程应在远程时释放 服务提供商系统问题已得到解决,但您经常会这样做 需要重新启动服务器实例(Java VM)才能清除所有内容 挂螺纹;特别是如果你缺乏适当的超时 实施
其他不太常见的原因包括:
- 巨大的响应数据导致读取/消耗套接字输入流所花费的时间增加,例如例如非常大的XML数据。这可以 通过分析响应数据的大小轻松证明
- 网络延迟导致从服务提供商到Java EE生产系统的数据传输所花费的时间增加。这个可以 通过在您的生产之间运行一些网络嗅探器来证明 服务器和服务提供商,并确定任何主要的延迟/延迟 问题
无论你的问题是什么,首先要做的是检查你的超时配置!
您需要为Jboss和Apache做一些配置。
server.xml 的主要问题是设置connectionTimeout 它设置底层套接字的SO_TIMEOUT。所以在连接时 Tomcat在指定的时间内没有收到请求 connectionTimeout,然后连接终止。这是必要的 因为如果连接已经使用了一段时间 时间那么它有可能在mod_jk结束时半闭。
如果连接未关闭,则会出现线程膨胀 这可以随着时间的推移达到Tomcat中的maxThreads计数,然后是Tomcat 无法接受任何新的连接。一个connectionTimeout 600000(10分钟)是一个很好的数字开始。可能有 连接没有足够快地回收的情况, 在这种情况下,connectionTimeout可以降低到60000或1 分钟。
在Tomcat中设置connectionTimeout时,mod_jk也应该有 connect_timeout / prepost_timeout设置,允许检测到 Tomcat连接已关闭并阻止重试请求。
maxThreads的建议值是每个CPU 200,所以我们假设 服务器是单核机器。如果它是四核,我们 可以将该值推到800,更多取决于RAM和其他 机器规格。
<Connector port="8009" address="${jboss.bind.address}" emptySessionPath="true" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" maxThreads="200" connectionTimeout="600000"></Connector>
查看内联评论。
worker.list=loadbalancer,status worker.template.port=8009 worker.template.type=ajp13 worker.template.lbfactor=1 #ping_timeout was introduced in 1.2.27 worker.template.ping_timeout=1000 #ping_mode was introduced in 1.2.27, if not #using 1.2.27 please specify connect_timeout=10000 #and prepost_timeout=10000 as an alternative worker.template.ping_mode=A worker.template.socket_timeout=10 #It is not necessary to specify connection_pool_timeout if you are running the worker mpm worker.template.connection_pool_timeout=600 #Referencing the template worker properties makes the workers.properties shorter and more concise worker.node1.reference=worker.template worker.node1.host=192.168.1.2 worker.node2.reference=worker.template worker.node2.host=192.168.1.3 worker.loadbalancer.type=lb worker.loadbalancer.balance_workers=node1,node2 worker.loadbalancer.sticky_session=True worker.status.type=status
上述workers.properties的关键点是我们已经添加了限制 对于mod_jk的连接。使用基本配置,socket 超时默认为无限。其他重要的属性是 ping_mode和ping_timeout,用于处理探测连接 错误和connection_pool_timeout必须设置为相等 使用prefork mpm时server.xml的connectionTimeout。当这些 在x的连接处于非活动状态后,两个值相同 时间量,mod_jk和Tomcat中的连接将关闭 同时,防止半封闭连接。
请注意,AJP连接的maxThreads应与之一致 在Apache的httpd.conf中设置的MaxClients。需要设置MaxClients 在Apache的正确模块中。
这可以通过运行
来确定httpd -V
:# httpd -V Server version: Apache/2.2.3 Server built: Sep 11 2006 09:43:05 Server's Module Magic Number: 20051115:3 Server loaded: APR 1.2.7, APR-Util 1.2.8 Compiled using: APR 1.2.7, APR-Util 1.2.7 Architecture: 32-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="/etc/httpd" -D SUEXEC_BIN="/usr/sbin/suexec" -D DEFAULT_PIDLOG="logs/httpd.pid" -D DEFAULT_SCOREBOARD="logs/apache_runtime_status" -D DEFAULT_LOCKFILE="logs/accept.lock" -D DEFAULT_ERRORLOG="logs/error_log" -D AP_TYPES_CONFIG_FILE="conf/mime.types" -D SERVER_CONFIG_FILE="conf/httpd.conf"
这告诉我Server MPM是Prefork。这并不总是100% 准确,所以你还应该查看/ etc / sysconfig / httpd的输出 看看是否有以下行:HTTPD = / usr / sbin / httpd.worker。如果 它被注释掉你正在运行prefork,否则如果没有注释 工人。
的httpd.conf:
<IfModule prefork.c> StartServers 8 MinSpareServers 5 MaxSpareServers 20 MaxClients 200 MaxRequestsPerChild 0 </IfModule>
如果Apache正在使用worker,那么
<IfModule worker.c> StartServers 2 MaxClients 200 MinSpareThreads 25 MaxSpareThreads 75 ThreadsPerChild 25 MaxRequestsPerChild 0 </IfModule>
MaxRequestsPerChild为0,这是使用时的建议值 mod_jk作为mod_jk保持打开持久连接。中的关键值 上面的配置是MaxClients和MaxRequestsPerChild ,. 其余值保留为默认值。请注意MaxRequestsPerChild 建议为0,但值可能需要大于0 取决于Apache是否也用于其他模块,特别是在 资源泄漏的情况。
在链接中,您可以找到另一种配置来优化此方案。