Web服务请求执行时间计算

Gan*_*row 12 java cxf

我有一个使用Java中的CXF实现的SOAP Web服务.在服务器端计算方法执行的好方法是什么?

我现在所做的是使用了拦截器.我public static long start在我的InInterceptor(Phase.RECEIVE)中定义了.在我的OutInterceptor(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");
    }
Run Code Online (Sandbox Code Playgroud)

有一个更好的方法吗?我正在阅读关于通过代理方法的执行,但我不知道如何做到这一点.

问题更新:

我用google搜索我的方式使用代理的第二种方式,即:

@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;
         }
    }
Run Code Online (Sandbox Code Playgroud)

根据目前对此问题的评论,使用拦截器比使用代理更好.我希望尽可能减慢网络服务的速度(这肯定会减慢速度),同时获得精确的性能测量.

Bij*_*men 10

我不建议您使用InInterceptor和OutInterceptor的第一种方法 - 原因是没有干净的方法来存储启动时间 - 您将令牌存储在静态变量中的方法将无法在线程环境中工作.

您使用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.");
}
Run Code Online (Sandbox Code Playgroud)

并在您为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>
Run Code Online (Sandbox Code Playgroud)


Juh*_*älä 5

根据matts的回答,我得出了以下结论.关键是在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");
        }
    }       
}
Run Code Online (Sandbox Code Playgroud)