2012-05-08 9 views
12

JavaでCXFで実装されたSOAP Webサービスが動作しています。サーバー側でメソッドの実行を計算するには、どのような方法が良いでしょうか?Webサービスリクエストの除外時間計算

私が今行ったことは、インターセプタを使用したことです。私は、InInterceptor(Phase.RECEIVE)にpublic static long startを定義しました。そして、私の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"); 
    } 

もっと良い方法がありますか?メソッドトラフプロキシの実行については読んでいましたが、どうやってそれを行うのかわかりません。

質問更新:

私はプロキシつまりを使用して第二の方法arroundの私の方法を見つけるもう少しググました:

インターセプタをされ使用して、これまでのところこの質問へのコメントに基づいて
@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サービスを遅くする(これは確かにそれを遅くする)と同時に、正確なパフォーマンス測定を得るために探しています。

+0

上記のメカニズムは良いと思います。 –

+0

私はインターセプタもお勧めしたいと思いますが、実際には役に立っているので – mtraut

答えて

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> 
+0

+1です。注意:Spring Securityを使用している場合は、それもフィルタを介して適用されることに注意してください。また、フィルタの順序に注意してセキュリティ層のタイミングを調整する必要がありますあなたが望むものに)。 –

3

私はあなたがそこに開始時間を保存し、後でそれは、経過時間を計算するためにバックアウト得ることができるので、インターセプタは、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ストアはメッセージマップ内の独自のデータの一部が、そのキーのほとんどはorg.apache.cxfまたはjavax.xml.wsで始まるので、あなただけの1の完全修飾クラス名を使用して、キーのユニークなマップを作ることができますあなたのインターセプタ。

+0

私はそれを試みましたが、動作しません。受信インターセプタでmessage.put()を使用して格納されたオブジェクトは、送信インターセプタのmessage.putで使用できません。 –

+0

Messageオブジェクトにリクエストの開始時刻情報を格納する代わりに、ThreadLocalにプッシュしてアウトバウンド・インターセプタで取り出すことができます。 –

0

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

Interceptorsを使用すると、CXFも測定されます。
は、アプリケーションロジックに関するメッセージの前後処理に使用されます。
Interceptorを使用すると、CXFフローの一部が測定されます。
これがあなたが望むものならOKです。
しかし、メソッドの実行を測定する場合は、メソッドとの関係でタイミング間隔を設定する必要があります。

4

matts' answerに基づいて、以下のことを確認しました。重要なのは、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"); 
     } 
    }  
} 
+0

あなたはmsg.getExchange()を使う必要があると思います。put/remove? – jontejj

+0

それは私のために働いてくれてありがとう:) – Niamath