在寻找一个Java-web应用程序的性能问题时,我想对一个单一的web会话进行分析(通过采样)。该web应用部署在Java EE应用服务器上(JBoss或WLS,所以不可能有OpenJDK专用的东西)。
使用传统的采样器,比如JVisualVM或YourKit,只能让我一次对所有正在运行的线程进行分析,因此不能显示出web-session的CPU使用情况,它与服务器上的基本负载是分开的。部分问题是,web-session和单个线程之间没有技术上的联系,也就是说,每个请求都可能从应用服务器的线程池中得到一个不同的线程。
我的想法是实现一个采样器,每次从服务器接收到新的请求时,注册与观察到的web-session相关联的线程(一旦请求结束,就会取消注册线程)。
第一个问题。你是必须手工完成还是有工具可以帮你完成?
第二个问题(因为我没有找到,并且假设这是一个相当特殊的问题)。最好的方法是什么?
很明显,人们会尽量减少剖析对应用性能的影响。同样很明显,由于我需要将(技术)线程信息连接到特定于应用程序的数据(websession-ID),这似乎没什么,可以通过JVMTI来完成。
这就留下了一个选择,即编码一个应用内的profiler,线程通过Thread.stackTrace或ThreadMXBean.getThreadInfo进行采样。哪个更好?有没有其他更好的方案?
JProfiler 可以针对不同的URL或查询参数拆分调用树。
如果你能为此修改URL或查询参数,那么你就能将会话与后台加载分开。例如,你可以添加一个查询参数 profile=true
你只传递给那些应该被剖析的请求。
声明:我的公司开发了JProfiler。
请看一下。
http:/messadmin.sourceforge.net。
这应该有助于你想要的资料。
还有: http:/www.appdynamics.com 和 http:/newrelic.com 都是非常好的分析网络应用的工具。
如果你没有JProfiler,"编写应用程序内的配置文件"当然是一种选择。在一个方法调用过程中,只需在特定的时间间隔内打印堆栈痕迹,就能提供一个很好的快照视图,了解正在发生的事情。
这里有一个帮助类的例子可以做到这一点。
import java.io.Closeable;
import java.io.IOException;
import java.lang.management.ManagementFactory;
public class StackDumper extends Thread implements Closeable {
static final String pid = ManagementFactory.getRuntimeMXBean().getName().replaceFirst("@.*", "");
final Thread t;
final int step;
public StackDumper(int timeStepMs) {
setName("Profiler");
this.t = Thread.currentThread();
this.step = timeStepMs;
start();
}
@Override
public void run() {
StringBuilder buf = new StringBuilder(4096);
for (int i = 0;; i += step) {
try {
Thread.sleep(step);
} catch (InterruptedException e) {
break;
}
buf.setLength(0);
for (StackTraceElement e : t.getStackTrace()) {
buf.append(" ").append(e).append('\n');
}
System.out.print(pid + " @" + i + "ms: [" + t.getName() + "]:\n" + buf);
}
}
@Override
public void close() throws IOException {
interrupt();
}
}
用它来做:
try (StackDumper p = new StackDumper(100)) { // prints stack every 100 ms ...
methodUnderTest();
}