12

Java で CXF を使用して実装された動作中の SOAP Web サービスがあります。サーバー側でメソッドの実行を計算するにはどうすればよいでしょうか?

今のところ行ったことは、インターセプターを使用したことです。public static long startInInterceptor(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");
    }

これを行うより良い方法はありますか?メソッドを介したプロキシの実行について読んでいましたが、その方法がわかりません。

質問の更新:

プロキシを使用して2番目の方法で自分の道を見つけるために、もう少しグーグルで検索しました:

@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 サービスの速度を可能な限り低下させ (これにより確実に速度が低下します)、同時に正確なパフォーマンス測定値を取得することを検討しています。

4

4 に答える 4

10

InInterceptor と OutInterceptor を使用する最初のアプローチはお勧めしません。その理由は、開始時刻を格納するクリーンな方法がないためです。静的変数にトークンを格納するアプローチは、スレッド化された環境では機能しません。

AOP を使用する 2 番目のアプローチは非常に優れていますが、CXF スタックで費やされた時間は提供されず、呼び出しがサービス層に到達した時点でのみ提供されます。

最良のアプローチはサーブレットフィルターを使用することだと思います。これを行うことができます:

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>
于 2012-05-10T22:12:56.473 に答える
5

マットの答えに基づいて、私は次のように解決しました。重要なのは、 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");
        }
    }       
}
于 2013-03-24T12:18:47.240 に答える
0

サーバー側でメソッドの実行を計算しますか?

あなたを使っInterceptorsて測定CXFしています!
つまり、アプリケーションロジックに関連しInterceptorsメッセージを前処理/後処理するために使用されます。 測定値の使用には、CXFフローチェーンの一部が含まれます。 これがあなたが望むものなら、OK。 ただし、メソッドの実行を測定する場合は、メソッドに関連するタイミング間隔を設定する必要があります。
Interceptor

于 2012-05-11T19:17:19.923 に答える