weblogic进程消耗cpu资源问题排查

系统管理员或用户注意到 WebLogic Server 进程消耗大量的 CPU 资源,并想要了解是哪个方面消耗了大量 CPU 资源,以及导致出现这种现象的原因。

故障排除

请注意,并非下面所有任务都需要完成。有些问题仅通过执行几项任务就可以解决。

为什么发生此问题?

收集高 CPU 占用率的数据

Solaris

Linux

AIX

HP-UX

Windows

外部资源

为什么发生此问题?
发生此问题有许多原因:WebLogic Server 本身、用户创建的线程、不良编码习惯或第三方软件。遗憾的是,证明在什么地方发生此问题有时候非常困难。本模式尝试通过利用特定操作命令和收集数据来帮助排除此问题。

收集高 CPU 占用率的数据
对于有关收集高 CPU 占用率的数据的特定操作信息,请根据您的操作系统执行以下步骤。

重要说明
这些操作系统的所有信息都基于 Sun JVM。 目前在 JRockit 中还没有办法将 PID 从说明 CPU 占用率的操作系统命令(prstat、top、pslist 等等)映射到 Thread Dump 中的正确线程。 从 Jrockit 的 70SP4RP2 和 81SP2RP1 以后的版本起,就可实现此映射。 例如,在 Linux 中,Thread Dump 在以后的版本中将采用如下形式(PID 显示在 Thread Dump 中):

"ExecuteThread: '20' for queue: 'default'" id: 0x00000e80 prio: 5 ACTIVE, DAEMON, GCABLE
thread: 0x469b0af0 lastj: 0xac0f19c
pt_thr: 237596 pid: 23166
at COM.jrockit.vm.Classes.defineClass0(Native Method)@0x8b4b798
at COM.jrockit.vm.Classes.defineClass(Unknown Source)@0x8b4b8b1
at java.lang.ClassLoader.defineClass(Unknown Source)@0x8b4b46f

在上例中,PID 是 23166,您可以通过 Linux 或任何所在系统上的 top(或任何您需要在操作系统上使用的特定命令)输出直接关联该 PID。
转换为十六进制号码
备注:为协助您计算在本模式中讨论的十六进制值,您可以在 Shell 脚本中使用下列行将十进制号码转换为十六进制号码。如果您使用 Unix 操作系统,那么转换会很方便。

dec2hex.sh:
printf "dec -> hex: %d = %x \n" ${
   1} ${
   1}

用法:

$ sh dec2hex.sh 755
dec -> hex: 755 = 2f3

Solaris

在 Java 进程中运行 prstat命令。重复几次这个操作,以便您能够看到一种模式。例如:prstat -L -p 1 1
在 Java 进程中运行 pstack命令以获得从轻量型进程 (LWP) 到 PID(进程 ID)的映射。
示例:pstack 9499 并将输出结果重定向到一个文件。
如果您使用 Solaris 中的常规线程库(即,在 LD_LIBRARY_PATH 中没有 /usr/lib/lwp),LWP 就不会直接映射到操作系统线程,因此您必须从进程中执行 pstack(所以检查看您是否正在使用替代线程库)。
经过一段时间后对服务器进行若干 Thread Dump,确保您执行正确的线程。
您可以通过在 Java 进程中执行 kill -3 来达到此目的。
将 LWP ID 映射到 Java 线程 ID。
例如,如果上述的 LWP 为“8”,它可以映射到 Java 线程“76”。然后将 76 换算为十六进制值 0x4c。
检查 Thread Dump,找到匹配“nid= <上述标识符/值>”的线程。
在本示例中,您找到匹配“nid=0x4c”的线程,而该线程就是正在消耗 CPU 资源的那个线程。
您将需要:
确定为什么在您的代码中会发生这个问题

或者,如果堆栈的最顶端输出来自 WebLogic,请与 BEA 客户支持部门联系。
下面是 Solaris 系统中上述进程的一个示例:
在 Java 进程中运行 prstat 命令。

$ prstat -L -p 9499 1 1
PID USERNAME SIZE RSS STATE PRI NICE TIME CPU PROCESS/LWPID
9499 usera 153M 100M sleep 58 0 0:00.22 0.6% java/8
9499 usera 153M 100M sleep 58 0 0:00.10 0.2% java/10
9499 usera 153M 100M sleep 58 0 0:00.11 0.1% java/9
9499 usera 153M 100M sleep 58 0 0:00.03 0.0% java/5
9499 usera 153M 100M sleep 58 0 0:01.01 0.0% java/1
9499 usera 153M 100M sleep 58 0 0:00.00 0.0% java/12
9499 usera 153M 100M sleep 58 0 0:00.00 0.0% java/11
9499 usera 153M 100M sleep 58 0 0:00.00 0.0% java/14
9499 usera 153M 100M sleep 58 0 0:00.00 0.0% java/13
9499 usera 153M 100M sleep 59 0 0:00.07 0.0% java/7
9499 usera 153M 100M sleep 59 0 0:00.00 0.0% java/6
9499 usera 153M 100M sleep 59 0 0:00.00 0.0% java/4
9499 usera 153M 100M sleep 58 0 0:00.11 0.0% java/3
9499 usera 153M 100M sleep 58 0 0:00.00 0.0% java/2

运行 pstack 命令。
示例:pstack 9499 并将输出结果重定向到一个文件。
如果您使用 Solaris 中的常规线程库(即,在 LD_LIBRARY_PATH 中没有 /usr/lib/lwp),LWP 就不会直接映射到操作系统线程,因此您必须从进程中执行 pstack(所以检查看您是否正在使用替代线程库)。

上述示例显示“java/8”进程在 prstat 的顶端。

为“lwp# 8”检验 pstack输出结果。
您会发现“lwp# 8”从 pstack 输出结果映射到“thread# 76”,如下所示。

lwp# 8 / thread# 76 ff29d190 poll (e2e81548, 0, bb8)
ff24d154 select (0, 0, 0, e2e81548, ff2bf1b4, e2e81548) + 348
ff36b134 select (0, bb8, 7fffffff, fe4c8000, 0, bb8) + 34
fe0f62e4 __1cCosFsleep6FpnGThread_xl_i_ (0, bb8, fe4c8000, 1, 0, 1e2fd8) + 234
fe23f050 JVM_Sleep (2, 0, bb8, fe4de978, fe4c8000, 1e2fd8) + 22c
0008f7ac ???????? (e2e818d4, bb8, 1e2fd8, 984a4, 0, 109a0)
0008c914 ???????? (e2e8194c, 1, fe4d6a80, 98564, 8, e2e81868)
fe5324e8 __1cMStubRoutinesG_code1_ (e2e819d8, e2e81c10, a, f6cb5000, 4, e2e818f0) + 3ec
fe0cbe94 __1cJJavaCallsLcall_helper6FpnJJavaValue_pnMmethodHandle_pnRJavaCallArguments_pnGThread__v_ (e2e81c08,fe4c8000, e2e81b54, 1e2fd8, 8e764, e2e81c10) +308
fe1f6dbc __1cJJavaCallsMcall_virtual6FpnJJavaValue_nLKlassHandle_nMsymbolHandlee81c08, e2e81b54) + 150pnGThread__v_(f6cb64b8, e2e81b40, e2e81b44, fe4c8000, e2d8) + 60e_5pnGThread__v_ (e2e81c08, e2e81c04, e2e81c00,e2e81bf4, e2e81bec, 1e2f8000, e2e81d10, 1e, e) + 120FpnKJavaThread_pnGThread__v_ (f6817ff8, 1e2fd8, fe4c
7fd70) + 3d8cKJavaThreadDrun6M_v_ (e2e02000, fe4d3e34, fe4c8000, 7fd70, 1e2fd8,
fe213ec8 _start (fe4c8000, fe625d10, 0, 5, 1, fe401000) + 20
ff36b728 _thread_start (1e2fd8, 0, 0, 0, 0, 0) + 40

通过在 Java 进程中执行以下命令对服务器进行 Thread Dump:
kill -3
由于 lwp# 8 映射到 thread #76,您可以将 76 换算为十六进制值 4c。
该值映射到 JVM Thread Dump 中的 nid=0x4c:

"Thread-6" prio=5 tid=0x1e2fd8 nid=0x4c waiting on monitor [0xe2e81000..0xe2e819d8]
at java.lang.Thread.sleep(Native Method)
at weblogic.management.deploy.GenericAppPoller.run(GenericAppPoller.java:139)

在此示例中,占用最多 CPU 资源的线程实际上正处于休眠状态。应用程序轮询程序在开发模式启动的服务器上运行。由于它每隔 30 秒运行一次,因此显然无法及时捕捉 Thread Dump 以了解此线程中的活动。

理想状态下,应当迅速并且连续完成全部三个步骤,以便尽可能及时地捕捉数据。这可以通过类似下面的一个简单的 shell 脚本来完成。

#
# Takes an argument (PID of the WLS process) and loops three times. This will append the prstat information to a file called dump_high_cpu.txt. The thread dump information will either be in file where stdout was redirected or printed on the screen.
#

for loopnum in 1 2 3
do
prstat -L -p $1 1 1 >> dump_high_cpu.txt
pstack $1 >> dump_high_cpu.txt
kill -3 $1
echo "prstat, pstack, and thread dump done. #" $loopnum
sleep 1
echo "Done sleeping."
done

然后,您可以检查该线程以确定它正在执行的任务以及是否出现问题。

Linux

获得最顶端输出并查找与之前启动了现占用 CPU 的 WLS 的那个用户 ID 相关联的 PID。
通过 kill -3 对 WebLogic Server 进行若干 Thread Dump
将步骤 1 中的 PID 号转换为一个十六进制值。
(用于 Linux 的 JVM 将 Java 线程作为本地线程实现,这使每个线程成为一个独立的 Linux 进程。)
在 Thread Dump 中搜索 nid 的值等于上一步骤中所得到的十六进制值的线程。
这将为您揭示造成高 CPU 占用率问题的线程。
确定为什么在您的代码中会发生这个问题,或者,如果堆栈的最顶端输出来自 WebLogic,请与 BEA 客户支持部门联系。
下面是 Linux 系统中上述进程的一个示例:
获得 top输出并查找与之前启动了现占用 CPU 的 WLS 的那个用户 ID 相关联的 PID。
将该号转换为一个十六进制值。
请参阅下面的 top 输出示例(这只是一个代码片断,因为对于单个 WLS 进程将启动更多的线程)。

在 Linux 中,每个线程映射到一个不同于其它 Unix 形式的进程中。

PID USER PRI NI SIZE RSS SHARE STAT %CPU %MEM TIME COMMAND
...........
22962 usera 9 0 86616 84M 26780 S 0.0 4.2 0:00 java
...........

如果 PID 为 22962,则十六进制值将是:0x59B2
使用此十六进制值并在 Thread Dump 中查找哪个 nid 等于该值,以便从 Thread Dump 中获取正确的线程。
例如,如果 ExecuteThread 0 出现问题,则 0x59B2 将对应于该线程:

"ExecuteThread: '0' for queue: 'default'" daemon prio=1 tid=0x83da550 nid=0x59b2 waiting on monitor [0x56138000..0x56138870]
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:415)
at weblogic.kernel.ExecuteThread.waitForRequest(ExecuteThread.java:146)
at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:172)

然后,您可以检查该线程以确定它正在执行的任务以及是否出现问题。
在上述示例中,由于该线程此时占用 0% 的 CPU,所以只显示执行此操作的进程。理想状态下,应当迅速并且连续完成全部三个步骤,以便尽可能及时地捕捉数据。这可以通过类似下面的一个简单的 shell 脚本来完成。

#
# Takes an argument (PID of the WLS process) and loops three times. This will append the prstat information to a file called dump_high_cpu.txt. The thread dump information will either be in file where stdout was redirected or printed on the screen.
#

for loopnum in 1 2 3
do
top -b -n1>> dump_high_cpu.txt
kill -3 $1
echo "cpu snapshot and thread dump done. #" $loopnum
sleep 1
echo "Done sleeping."
done

AIX

执行: ps -mp -o THREAD 以查找正在占用 CPU 的 tid。
您应当查看“CP”列(表示 CPU 占用率),看其中哪些线程的此项值比较高并从中挑选一个线程。
通过执行以下命令对服务器进行 Thread Dump:
kill -3
运行: dbx -a
在 dbx 中时,运行 dbx thread命令(以列出所有线程)。
查找与您通过 ps -mp
该行中的号码应当采用“$t”格式,其中“NUM”是一个号码。
在 dbx 中时,运行 dbx 命令 th info (此 TID 来自上一步骤,该步骤在 $t后面列出号码)以获取关于该线程的信息。
从第 3 步骤的输出中,在“general”下查找“pthread_t”,并记录该十六进制号码。
非常重要说明:在 dbx 提示符下,您需要在完成操作时在 dbx 命令行键入“detach”,否则,如果您在连接到进程时只要一退出,dbx 将终止该进程!
记下“p_thread_t”输出中的十六进制值,并在 Thread Dump 中搜索其中哪个线程的“native ID”等于该值。
这将为您揭示造成高 CPU 占用率问题的线程。

确定为什么在您的代码中正在发生这个问题,或者,如果堆栈的最顶端输出来自 WebLogic,请与 BEA 客户支持部门联系。
下面是 AIX 系统中上述进程的一个示例:
ps -mp 250076 -o THREAD 将显示以下内容:

USER PID PPID TID ST CP PRI SC WCHAN F TT BND COMMAND
usera 250076 217266 - A 38 60 72 * 242011 pts/0 - /wwsl/sharedInstalls/aix/jdk130/...
- - - 315593 Z 0 97 1 - c00007 - - -
- - - 344305 S 0 60 1 f1000089c020e200 400400 - - -
- - - 499769 S 0 60 1 f1000089c0213a00 400400 - - -
- - - 540699 S 0 60 1 f100008790008440 8410400 - - -
- - - 544789 S 0 60 1 f100008790008540 8410400 - - -
- - - 548883 S 0 60 1 f100008790008640 8410400 - - -
- - - 552979 S 0 60 1 f100008790008740 8410400 - - -
- - - 565283 Z 0 60 1 - c00007 - - -
- - - 585783 S 0 60 1 f100008790008f40 8410400 - - -
- - - 589865 Z 0 80 1 - c00007 - - -
- - - 593959 S 1 60 1 f100008790009140 8410400 - - -
- - - 610365 S 0 60 1 f100008790009540 8410400 - - -
- - - 614453 S 0 60 1 f100008790009640 8410400 - - -
- - - 618547 S 0 60 1 f100008790009740 8410400 - - -
- - - 622645 S 0 60 1 f100008790009840 8410400 - - -
- - - 626743 S 0 60 1 f100008790009940 8410400 - - -
- - - 630841 S 0 60 1 f100008790009a40 8410400 - - -
- - - 634941 S 0 60 1 f100008790009b40 8410400 - - -
- - - 639037 S 0 60 1 f100008790009c40 8410400 - - -
- - - 643135 S 0 60 1 f100008790009d40 8410400 - - -
- - - 647233 S 0 60 1 f100008790009e40 8410400 - - -
- - - 651331 S 0 60 1 f100008790009f40 8410400 - - -
- - - 655429 S 0 60 1 f10000879000a040 8410400 - - -
- - - 659527 S 0 60 1 f10000879000a140 8410400 - - -
- - - 663625 S 0 60 1 f10000879000a240 8410400 - - -
- - - 667723 S 37 78 1 f1000089c020f150 400400 - - -
- - - 671821 S 0 60 1 f10000879000a440 8410400 - - -
- - - 675919 S 0 60 1 - 418400 - - -
- - - 680017 S 0 60 1 f10000879000a640 8410400 - - -
- - - 684115 S 0 60 1 f10000879000a740 8410400 - - -
- - - 688213 S 0 60 1 f10000879000a840 8410400 - - -
- - - 692311 S 0 60 1 f10000879000a940 8410400 - - -
- - - 696409 S 0 60 1 f10000879000aa40 8410400 - - -
- - - 712801 S 0 60 1 f10000879000ae40 8410400 - - -
- - - 716899 S 0 60 1 f10000879000af40 8410400 - - -
- - - 721011 S 0 60 1 f10000879000b040 8410400 - - -
- - - 725095 S 0 60 1 f10000879000b140 8410400 - - -
- - - 729193 S 0 60 1 f10000879000b240 8410400 - - -
- - - 733291 S 0 60 1 f10000879000b340 8410400 - - -
- - - 737389 S 0 60 1 f10000879000b440 8410400 - - -
- - - 741487 S 0 60 1 f10000879000b540 8410400 - - -
- - - 745585 S 0 60 1 f10000879000b640 8410400 - - -
- - - 749683 S 0 60 1 f10000879000b740 8410400 - - -
- - - 753781 S 0 60 1 f10000879000b840 8410400 - - -
- - - 757879 S 0 60 1 f10000879000b940 8410400 - - -
- - - 761977 S 0 60 1 f10000879000ba40 8410400 - - -
- - - 766075 S 0 60 1 f10000879000bb40 8410400 - - -
- - - 770173 S 0 60 1 f10000879000bc40 8410400 - - -
- - - 774271 Z 0 60 1 - c00007 - - -
- - - 778373 S 0 60 1 f10000879000be40 8410400 - - -
- - - 782467 S 0 60 1 f10000879000bf40 8410400 - - -
- - - 786565 S 0 60 1 f10000879000c040 8410400 - - -
- - - 790663 S 0 60 1 f10000879000c140 8410400 - - -
- - -
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值