Java Web服务请求执行时间计算
我用Java中的CXF实现了一个工作的SOAP web服务。在服务器端计算方法执行的好方法是什么 我现在做的是使用拦截器。我已经在我的InInterceptor(Phase.RECEIVE)中定义了Java Web服务请求执行时间计算,java,cxf,Java,Cxf,我用Java中的CXF实现了一个工作的SOAP web服务。在服务器端计算方法执行的好方法是什么 我现在做的是使用拦截器。我已经在我的InInterceptor(Phase.RECEIVE)中定义了公共静态长启动。在我的OutiterCeptor(Phase.SEND)中,我计算响应时间如下: @Override public void handleMessage(Message arg0) { long stop = System.currentTimeMill
公共静态长启动
。在我的OutiterCeptor(Phase.SEND)中,我计算响应时间如下:
@Override
public void handleMessage(Message arg0) {
long stop = System.currentTimeMillis();
long executionTime = stop - RequestStartInterceptor.start;
System.out.println("execution time was ~" + executionTime + " ms");
}
有更好的方法吗?我读过关于通过代理执行方法的文章,但我不知道如何去做
问题更新:
我在谷歌上搜索了更多关于使用代理的第二种方法的信息,即:
@Aspect
public class MyServiceProfiler {
@Pointcut("execution(* gov.noaa.nhc.*.*(..))")
public void myServiceMethods() { }
@Around("myServiceMethods()")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("Going to call the method.");
Object output = pjp.proceed();
System.out.println("Method execution completed.");
long elapsedTime = System.currentTimeMillis() - start;
System.out.println("Method execution time: " + elapsedTime + " milliseconds.");
return output;
}
}
根据到目前为止对这个问题的评论,使用拦截器比使用代理要好。我希望尽可能降低Web服务的速度(这肯定会降低速度)同时获得精确的性能度量。我不推荐您使用InInterceptor和OutInterceptor的第一种方法-原因是没有干净的方法来存储starttime-将其存储在静态变量中的方法在线程环境中不起作用 第二种使用AOP的方法非常好,但是它不会给出在CXF堆栈中花费的时间,它只会在调用到达服务层时提供时间 我觉得最好的方法是使用servlet过滤器,您可以这样做:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
long start = System.currentTimeMillis();
chain.doFilter(request, response);
long elapsedTime = System.currentTimeMillis() - start;
System.out.println("Method execution time: " + elapsedTime + " milliseconds.");
}
并在为CXFServlet提供映射的同一uri上提供映射
这应该干净得多。如果您想要更细粒度的东西,您可以将此方法与AOP方法混合,以找到总体响应时间,然后将其分解为各个服务方法时间
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/webservices/*</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>ExecTimeFilter</filter-name>
<url-pattern>/webservices/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
CXF服务器
org.apache.cxf.transport.servlet.CXFServlet
CXF服务器
/网络服务/*
执行时间过滤器
/网络服务/*
要求
我认为拦截器可以在消息
对象中放入任意数据,因此您可以将开始时间存储在那里,然后再将其取出以计算经过的时间
// in your receive interceptor
@Override
public void handleMessage(Message message) {
long startTime = System.currentTimeMillis();
message.put("my.timing.start", startTime);
}
CXF在消息映射中存储自己的一些数据,但它的大多数键都以org.apache.CXF
或javax.xml.ws
开头,因此您可以使用一个拦截器的完全限定类名使映射键唯一
在服务器端计算方法执行
使用拦截器
您也在测量CXF
我的意思是,
拦截器
用于预处理/后处理与应用程序逻辑相关的消息。使用
拦截器
您的测量包括CXF流链的一部分。如果这是您想要的,那么可以。
但是如果你想测量你的方法执行情况,你应该把时间间隔与你的方法联系起来。基于我计算出的以下内容。关键是在OutgoingInterceptor中,您需要获取传入消息并从中获取起始时间戳
public class IncomingInterceptor extends AbstractPhaseInterceptor<Message> {
public IncomingInterceptor() {
super(Phase.RECEIVE);
}
@Override
public void handleMessage(Message msg) throws Fault {
long startTime = System.currentTimeMillis();
msg.put("my.timing.start", startTime);
}
}
public class OutgoingInterceptor extends AbstractPhaseInterceptor<Message> {
Logger log = LoggerFactory.getLogger(AbstractPhaseInterceptor.class);
public OutgoingInterceptor() {
super(Phase.SEND);
}
@Override
public void handleMessage(Message msg) throws Fault {
Long startTime = (Long)msg.getExchange().getInMessage().remove("my.timing.start");
if (startTime != null) {
long executionTime = System.currentTimeMillis() - startTime;
log.info("execution time was ~" + executionTime + " ms");
} else {
log.info("timer not found");
}
}
}
公共类IncomingInterceptor扩展AbstractPhaseInterceptor{
公共收入拦截器(){
超级(相位接收);
}
@凌驾
public void handleMessage(Message msg)引发错误{
long startTime=System.currentTimeMillis();
msg.put(“my.timening.start”,startTime);
}
}
公共类OutgoingInterceptor扩展了AbstractPhase Interceptor{
Logger log=LoggerFactory.getLogger(AbstractPhaseInterceptor.class);
公共支出接受者(){
super(Phase.SEND);
}
@凌驾
public void handleMessage(Message msg)引发错误{
Long startTime=(Long)msg.getExchange().getInMessage().remove(“my.timing.start”);
if(startTime!=null){
long executionTime=System.currentTimeMillis()-startTime;
log.info(“执行时间为~”+执行时间+“毫秒”);
}否则{
日志信息(“未找到计时器”);
}
}
}
我认为上面的机制很好。我建议使用拦截器,我尝试过了,但它不起作用,使用message.put()在接收拦截器中存储的对象无法通过message.put在发送拦截器中使用。与其将请求开始时间信息存储在message对象中,您可以将其推入ThreadLocal,然后在出站拦截器中检索它。+1确实非常有用。注意:如果您使用的是Spring安全性,请注意它也是通过过滤器应用的,您需要注意过滤器的顺序,以确保您也对安全层进行计时(或者不计时,取决于您想要什么)。我认为您需要使用msg.getExchange().put/remove?
public class IncomingInterceptor extends AbstractPhaseInterceptor<Message> {
public IncomingInterceptor() {
super(Phase.RECEIVE);
}
@Override
public void handleMessage(Message msg) throws Fault {
long startTime = System.currentTimeMillis();
msg.put("my.timing.start", startTime);
}
}
public class OutgoingInterceptor extends AbstractPhaseInterceptor<Message> {
Logger log = LoggerFactory.getLogger(AbstractPhaseInterceptor.class);
public OutgoingInterceptor() {
super(Phase.SEND);
}
@Override
public void handleMessage(Message msg) throws Fault {
Long startTime = (Long)msg.getExchange().getInMessage().remove("my.timing.start");
if (startTime != null) {
long executionTime = System.currentTimeMillis() - startTime;
log.info("execution time was ~" + executionTime + " ms");
} else {
log.info("timer not found");
}
}
}