JBoss CPU利用率问题

发布于 2024-11-15 02:06:08 字数 796 浏览 4 评论 0原文

我正在使用 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 利用率仍然与处于相同状态的线程相同。

I am using JBoss AS 4.2.3 along with the seam framework. My CPU usage increases as the number of users increase and it hits 99% for just 80 users. We also use Hibernate, EJB3 and Apache with mod_jk for loadbalancing.

When I took the thread dump all the runnable threads are doing a same activity with the following trace:

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)

I am not able to interpret this with the stack trace. Also I find that even when the users have logged out, the CPU utilization still continues to be the same with threads in the same state.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无声无音无过去 2024-11-22 02:06:08

这些线程正在尝试从 Socket 连接读取数据。在这种情况下,它们正在等待从 Apache 中的 mod_jk 发送到服务器的下一个请求。这是很正常的,它们可能不是您的 CPU 使用率的原因。

此时,您确实需要通过分析器运行您的应用程序。

如果您无法在系统上运行探查器(即它是一个生产设备),那么下一个最好的办法是开始每隔几秒进行多次堆栈转储,然后手动检查它们以匹配线程 ID。您需要查找正在运行代码并且在转储之间似乎没有更改的线程。

这是一项非常乏味的任务,并不总能得到清晰的结果,但如果没有分析器或某种仪器,您将无法找到所有 CPU 的去向。

These threads are attempting to read from a Socket connection. In this case they are waiting for the next request to be sent to the server from mod_jk in Apache. This is quite normal and they probably are not the reason for your CPU usage.

At this point you really need to go and run your application through a profiler.

If you are unable to run a profiler on the system (i.e. it's a production box) the next best thing is to start to take many stack dumps each a couple of seconds apart and then go though them by hand matching up the thread IDs. You need to look for the threads that are running your code and don't seem to have changed between dumps.

It is a very tedious task and doesn't always get clear results, but without a profiler or some sort of instrumentation you won't be able to find where all that CPU is going.

紫﹏色ふ单纯 2024-11-22 02:06:08

检查 Apache 和 Jboss 之间的 AJP 配置,如 https://developer.jboss.org/wiki/OptimalModjk12Configuration 中所述

问题

JBoss Web (Tomcat) server.xml AJP 片段:

<连接器端口=“8009”地址=“${jboss.bind.address}”协议=“AJP/1.3”
         emptySessionPath =“true”enableLookups =“false”redirectPort =“8443”&gt;&lt;/连接器&gt; Apache 的 httpd.conf:

;
启动服务器 8
最少备用服务器 5
最大备用服务器数 20
服务器限制 256
最大客户数 256
每个孩子的最大请求数 4000

以上配置,在负载下,可能会导致mod_jk非常慢
并且无响应,导致http错误,导致半关闭
连接。这些问题之所以会出现,是因为没有
指定连接超时来处理孤立连接,无
在workers.properties中定义的错误处理属性,并且没有
Apache 和 Tomcat 中设置的连接限制。

但如此大量的线程可能来自另一个来源。如此处所述:

挂起 Socket.read() 的最常见情况是高
处理时间或远程服务提供商的不健康状态。
这意味着您需要与服务提供商沟通
立即支持团队,以确认他们是否面临一些问题
他们的系统出现减速情况。

一旦远程连接,您的应用程序服务器线程就应该被释放
服务提供商系统问题已解决,但通常您会
需要重新启动服务器实例(Java VM)以清除所有
悬挂线程;特别是如果你缺乏适当的超时时间
实施。

其他不太常见的原因包括:

  • 巨大的响应数据会导致读取/消耗套接字输入流的时间增加,例如非常大的 XML 数据。这可以是
    通过分析响应数据的大小可以轻松证明
  • 网络延迟导致从服务提供商到 Java EE 生产系统的数据传输时间增加。这个可以
    通过在生产之间运行一些网络嗅探器来证明
    服务器和服务提供商并确定任何主要的滞后/延迟
    问题

无论您遇到什么问题,首先要做的就是检查您的超时配置!

你能做什么?

您需要对 Jboss 和 Apache 进行一些配置。

JBoss端

server.xml的主要问题是设置connectionTimeout
它设置底层套接字的 SO_TIMEOUT。所以当一个连接进入
Tomcat 在指定的时间内没有收到请求
连接超时,然后连接就断开了。这是必要的
因为如果连接在一段时间内没有被使用
时间,那么 mod_jk 端有可能是半关闭的。

如果连接未关闭,则会出现线程膨胀
随着时间的推移,它可能会达到 Tomcat 中的 maxThreads 计数,然后 Tomcat 将
无法接受任何新连接。连接超时时间为
600000(10 分钟)是一个不错的起始数字。可能有
连接回收速度不够快的情况,
在这种情况下,connectionTimeout 可以降低到 60000 或 1
分钟。

在Tomcat中设置connectionTimeout时,mod_jk也应该有
connect_timeout/prepost_timeout 设置,允许检测
Tomcat 连接已关闭并阻止重试请求。

maxThreads 的建议值为每个 CPU 200,所以这里我们假设
服务器是单核机器。如果是四核,我们
可以将该值推至 800,更多取决于 RAM 和其他
机器规格。

<连接器端口=“8009”
           地址=“${jboss.bind.地址}”
           空会话路径=“真”
           启用查找=“假”
           重定向端口=“8443”
           协议=“AJP/1.3”
           最大线程数=“200”
           connectionTimeout="600000">

Apache 端的

worker.properties 文件

查看内嵌评论。

worker.list=负载均衡器,状态

工人.模板.端口=8009
工人.模板.类型=ajp13
工人.模板.lbfactor = 1
#ping_timeout 于 1.2.27 引入
工人.模板.ping_timeout = 1000
#ping_mode是在1.2.27引入的,如果没有的话 
#使用1.2.27请指定connect_timeout=10000 
#and prepost_timeout=10000 作为替代方案
工人.template.ping_mode=A
工人.模板.socket_timeout = 10
#如果运行worker mpm则不需要指定connection_pool_timeout 
工人.模板.connection_pool_timeout = 600

#引用模板worker属性使workers.properties更短更简洁
worker.node1.reference=worker.template
工人.node1.host=192.168.1.2

worker.node2.reference=worker.template
工人.node2.主机=192.168.1.3

工作负载均衡器类型=lb
worker.loadbalancer.balance_workers=节点1,节点2
worker.loadbalancer.sticky_session=True

工人.status.type=状态

上面的workers.properties中的关键点是我们添加了限制
对于 mod_jk 建立的连接。与基本配置、插座
超时默认为无限。其他重要的属性是
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

服务器版本:Apache/2.2.3
服务器建成:2006 年 9 月 11 日 09:43:05
服务器模块魔数:20051115:3
服务器加载:APR 1.2.7、APR-Util 1.2.8
编译使用:APR 1.2.7、APR-Util 1.2.7
架构:32位
服务器 MPM:预分叉
螺纹:无
forked:是(可变进程数)
服务器编译为....
-D APACHE_MPM_DIR="服务器/mpm/prefork"
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6(启用 IPv4 映射地址)
-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="日志/apache_runtime_status"
-D DEFAULT_LOCKFILE="logs/accept.lock"
-D DEFAULT_ERRORLOG="日志/错误日志"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"

这告诉我服务器 MPM 是 Prefork。这并不总是 100%
准确,因此您还应该查看 /etc/sysconfig/httpd 的输出
查看是否存在以下行:HTTPD=/usr/sbin/httpd.worker。如果
它被注释掉你正在运行 prefork,否则如果未注释
工人。

httpd.conf:

;
启动服务器 8
最少备用服务器 5
最大备用服务器数 20
最大客户数 200
每个子项的最大请求数 0

或者如果 Apache 正在使用worker,那么它就是

;
启动服务器2
最大客户数 200
最小备用线程 25
最大备用线程数 75
每个子线程数 25
每个子项的最大请求数 0

MaxRequestsPerChild为0,这是使用时的推荐值
mod_jk 因为 mod_jk 保持打开的持久连接。中的关键值
上面的配置是MaxClients和MaxRequestsPerChild,
其余值保留为默认值。请注意,MaxRequestsPerChild
建议为 0,但该值可能需要大于 0
取决于 Apache 是否也用于其他模块,特别是在
资源泄漏的情况。

在链接中,您可以找到另一个配置来进一步优化此场景。

Review your AJP configuration between Apache and Jboss, as described in https://developer.jboss.org/wiki/OptimalModjk12Configuration

The problem

JBoss Web's (Tomcat) server.xml AJP snippet:

<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>

The above configuration, under load, may cause mod_jk to be very slow
and unresponsive, cause http errors, and cause half-closed
connections. These problems can arise because there are no
connection timeouts specified to take care of orphaned connections, no
error handling properties defined in workers.properties, and no
connection limits set in Apache and Tomcat.

But this high number of threads could be from another source. As described here:

the most common scenario for a hanging Socket.read() is a high
processing time or unhealthy state of your remote service provider.
This means that you will need to communicate with the service provider
support team right away in order to confirm if they are facing some
slowdown condition on their system.

Your applicaton server Threads should be released once the remote
service provider system problem is resolved but quite often you will
need to restart your server instances (Java VM) to clear all the
hanging Threads; especially if you are lacking proper timeout
implementation.

Other less common causes include:

  • Huge response data causing increased elapsed time to read / consume the Socket Inputstream e.g. such as very large XML data. This can be
    proven easily by analysing the size of the response data
  • Network latency causing increased elapsed time in data transfer from the service provider to your Java EE production system. This can
    be proven by running some network sniffer between your production
    server and the service provider and determine any major lag/latency
    problem

Whatever was your problem, the first thing to do is review your timeout configuration!

What you can do?

You need to do some configuration for Jboss and Apache.

JBoss side

The main concern with server.xml is setting the connectionTimeout
which sets the SO_TIMEOUT of the underlying socket. So when a connection in
Tomcat hasn't had a request in the amount of time specified by
connectionTimeout, then the connection dies off. This is necessary
because if the connection hasn't been used for a certain period of
time then there is the chance that it is half-close on the mod_jk end.

If the connection isn't closed there will be an inflation of threads
which can over time hit the maxThreads count in Tomcat then Tomcat will
not be able to accept any new connections. A connectionTimeout of
600000 (10 minutes) is a good number to start out with. There may be
a situation where the connections are not being recycled fast enough,
in this instance the connectionTimeout could be lowered to 60000 or 1
minute.

When setting connectionTimeout in Tomcat, mod_jk should also have
connect_timeout/prepost_timeout set, which allows detection that the
Tomcat connection has been closed and preventing a retry request.

The recommended value of maxThreads is 200 per CPU, so here we assume
the server is a single core machine. If it has been quad core, we
could push that value to 800, and more depending on RAM and other
machine specs.

<Connector port="8009"
           address="${jboss.bind.address}"
           emptySessionPath="true"
           enableLookups="false"
           redirectPort="8443"
           protocol="AJP/1.3"
           maxThreads="200"
           connectionTimeout="600000"></Connector>

Apache side

worker.properties file

See comments inline.

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

The key points in the above workers.properties is we've added limits
for the connections mod_jk makes. With the base configuration, socket
timeouts default to infinite. The other important properties are
ping_mode and ping_timeout which handle probing a connection for
errors and connection_pool_timeout which must be set to equal
server.xml's connectionTimeout when using the prefork mpm. When these
two values are the same, after a connection has been inactive for x
amount of time, the connection in mod_jk and Tomcat will be closed at
the same time, preventing a half-closed connection.

Apache configuration

Make note that maxThreads for the AJP connection should coincide with
the MaxClients set in Apache's httpd.conf. MaxClients needs to be set
in the correct module in Apache.

This can be determined by running 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"

Which tells me the Server MPM is Prefork. This is not always 100%
accurate so you should also view the output of /etc/sysconfig/httpd to
see if the following line is there: HTTPD=/usr/sbin/httpd.worker. If
it is commented out you are running prefork, otherwise if uncommented
worker.

httpd.conf:

<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
MaxClients       200
MaxRequestsPerChild  0
</IfModule>

Or if Apache is using worker, it is

<IfModule worker.c>
StartServers         2
MaxClients         200
MinSpareThreads     25
MaxSpareThreads     75
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>

MaxRequestsPerChild is 0, this is the recommended value when using
mod_jk as mod_jk keeps open persistent connections. The key values in
the above configuration are MaxClients and MaxRequestsPerChild, the
rest of the values are left as default. Note that MaxRequestsPerChild
is recommended to be 0 however the value may need to be greater than 0
depending on if Apache is used for other modules also, especially in
the case of resource leakage.

In the link you can find another configuration to optimize even more this scenario.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文