java Web服务请求执行时间计算

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10504189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 01:20:07  来源:igfitidea点击:

Web service request exection time calculation

javacxf

提问by Gandalf StormCrow

I have a working SOAP web service implemented with CXF in Java. What would be a good way to calculate method execution on a server side?

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

What I've done for now is I used interceptors. I've defined public static long startin my InInterceptor(Phase.RECEIVE). And in my OutInterceptor(Phase.SEND) I calculate response time like this :

我现在所做的是使用拦截器。我已经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");
    }

Is there a better way to do this? I was reading about execution of method trough proxy, but I have no clue how to do that.

有一个更好的方法吗?我正在阅读有关通过代理执行方法的信息,但我不知道该怎么做。

Question update :

问题更新:

I've googled a bit more a find my way arround the second way using the proxy i.e :

我在谷歌上搜索了更多,找到了使用代理的第二种方式,即:

@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;
         }
    }

Based on comments to this question so far, using interceptors is better than using proxy. I'm looking to slow down the webservice as least as possible (this will certainly slow it down) and at the same time get a precise performance measurement.

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

采纳答案by Biju Kunjummen

I wouldn't recommend your first approach of using InInterceptor and OutInterceptor - the reason is there is no clean way to store the starttime - the approach that you have token to store it in a static variable will not work in a threaded environment.

我不会推荐您使用 InInterceptor 和 OutInterceptor 的第一种方法 - 原因是没有干净的方法来存储开始时间 - 您有令牌将其存储在静态变量中的方法在线程环境中不起作用。

Your second approach of using AOP is very good, however it will not give the time spent in the CXF stack, it will only provide the time once the call comes to your service tier.

您使用 AOP 的第二种方法非常好,但是它不会给出在 CXF 堆栈中花费的时间,它只会在调用到达您的服务层时提供时间。

I feel the best approach will be using a servlet filter, you can do this:

我觉得最好的方法是使用 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.");
}

and provide the mapping at the same uri where you have provided the mapping for CXFServlet.

并在您为 CXFServlet 提供映射的同一 uri 中提供映射。

This should be much more cleaner. If you want something even more granular, you can mix this approach with your AOP approach to find the overall response time and then break it down into the individual service method times.

这应该更干净。如果您想要更精细的东西,您可以将此方法与您的 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>

回答by Juha Syrj?l?

Based on matts' answerI worked out following. The key is that in OutgoingInterceptor you need get incoming message and obtain starting timestamp from that.

根据马特的回答,我制定了以下内容。关键是在 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");
        }
    }       
}

回答by matts

I think interceptors can put arbitrary data in the Messageobject, so you can store the start time there and later get it back out to compute the time elapsed.

我认为拦截器可以将任意数据放入Message对象中,因此您可以将开始时间存储在那里,然后再将其取出以计算经过的时间。

// in your receive interceptor
@Override
public void handleMessage(Message message) {
    long startTime = System.currentTimeMillis();
    message.put("my.timing.start", startTime);
}

.

.

// in your send interceptor
@Override
public void handleMessage(Message message) {
    Long startTime = message.remove("my.timing.start");
    if (startTime != null) {
        long executionTime = System.currentTimeMillis() - startTime;
        System.out.println("execution time was ~" + executionTime + " ms");
    }
}

CXF stores some of its own data in the message map, but most of its keys start with org.apache.cxfor javax.xml.ws, so you can just make your map key unique by using the fully-qualified class name of one of your interceptors.

CXF 在消息映射中存储它自己的一些数据,但它的大多数键都以org.apache.cxf或开头javax.xml.ws,因此您可以使用拦截器之一的完全限定类名来使映射键唯一。

回答by Cratylus

calculate method execution on a server side?

在服务器端计算方法执行?

Using Interceptorsyou are measuring CXFas well!
I mean Interceptorsare used to pre/post process a message in relation to yourapplication logic.
Using the Interceptoryour measurements include parts of the CXF chain of flow.
If this is what you want then ok.
But if you want to measure your method execution you should put the timing interval in relation to your method.

使用Interceptors你也在测量CXF
我的意思Interceptors是用于预处理/后处理与您的应用程序逻辑相关的消息。
使用Interceptor您的测量包括 CXF 流链的一部分。
如果这就是你想要的,那么就可以了。
但是如果你想测量你的方法执行,你应该把时间间隔与你的方法相关联。