2012-05-08 18 views
12

Ho un servizio Web SOAP funzionante implementato con CXF in Java. Quale sarebbe un buon modo per calcolare l'esecuzione del metodo da un lato server?Calcolo dell'ora di richiesta del servizio Web

Quello che ho fatto per ora è che ho usato gli intercettatori. Ho definito public static long start nel mio InInterceptor (Phase.RECEIVE). E nella mia OutInterceptor (Phase.SEND) a calcolare il tempo di risposta in questo modo:

@Override 
    public void handleMessage(Message arg0) { 
     long stop = System.currentTimeMillis(); 
     long executionTime = stop - RequestStartInterceptor.start; 
     System.out.println("execution time was ~" + executionTime + " ms"); 
    } 

Esiste un modo migliore per fare questo? Stavo leggendo sull'esecuzione del metodo tramite proxy, ma non ho idea di come farlo.

aggiornamento Domanda:

Googled un po 'più di una trovare la mia strada arround il secondo modo utilizzando la delega vale a dire:

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

Sulla base di commenti a questa domanda finora, utilizzando intercettori è meglio di usare il proxy. Sto cercando di rallentare il meno possibile il webservice (questo certamente lo rallenterà) e allo stesso tempo ottenere una misurazione precisa delle prestazioni.

+0

Penso che il meccanismo di cui sopra sia buono. –

+0

Consiglierei gli interceptor, anche – mtraut

risposta

10

Non consiglio il primo approccio all'utilizzo di InInterceptor e OutInterceptor - il motivo è che non esiste un modo pulito per archiviare l'ora di inizio - l'approccio che hai token per memorizzarlo in una variabile statica non funzionerà in un thread ambiente.

Il tuo secondo approccio all'utilizzo di AOP è molto buono, tuttavia non fornirà il tempo trascorso nello stack CXF, ma fornirà l'ora solo quando la chiamata arriva al tuo livello di servizio.

mi sento il migliore approccio verrà utilizzato un filtro servlet, si può fare questo:

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."); 
} 

e fornire la mappatura allo stesso URI in cui ci avete fornito la mappatura per CXFServlet.

Questo dovrebbe essere molto più pulito. Se si desidera qualcosa di ancora più granulare, è possibile combinare questo approccio con l'approccio AOP per trovare il tempo di risposta complessivo e quindi scomporlo nei tempi del metodo di servizio individuale.

<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 per essere veramente utile. Una nota: se stai utilizzando Spring Security, tieni presente che viene applicato anche tramite un filtro e che devi fare attenzione con l'ordine dei filtri per assicurarti di sincronizzare anche il livello di sicurezza (o meno, a seconda su quello che vuoi). –

3

Penso agli intercettori possono mettere dati arbitrari nell'oggetto Message, in modo da poter memorizzare l'ora di inizio lì e poi ottenere di nuovo fuori per calcolare il tempo trascorso.

// 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"); 
    } 
} 

negozi CXF alcuni dei propri dati nella mappa di messaggi, ma la maggior parte dei suoi tasti iniziano con org.apache.cxf o javax.xml.ws, quindi si può solo rendere la vostra mappa unica chiave utilizzando il nome completo della classe di uno dei i tuoi intercettori.

+0

Ho provato che, e non funzionerà, gli oggetti memorizzati usando message.put() nell'intercettore di ricezione non sono disponibili tramite message.put nell'interceptor di invio. –

+0

Invece di memorizzare le informazioni sull'ora di inizio della richiesta nell'oggetto Messaggio, è possibile passare a ThreadLocal e quindi recuperarlo nell'intercettore in uscita. –

0

calcolare l'esecuzione del metodo su un lato server?

Utilizzando Interceptors si sta misurando CXF pure!
Voglio dire che Interceptors sono utilizzati per pre/postare un messaggio in relazione a la logica dell'applicazione.
Utilizzando lo Interceptor le misurazioni includono parti della catena di flusso CXF.
Se questo è quello che vuoi allora ok.
Ma se si desidera misurare l'esecuzione del metodo, è necessario impostare l'intervallo di temporizzazione in relazione al proprio metodo.

4

Sulla base di matts' answer ho lavorato seguendo. La chiave è che in OutgoingInterceptor è necessario ottenere il messaggio in arrivo e ottenere il timestamp iniziale da quello.

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

Penso che sia necessario utilizzare msg.getExchange(). Put/remove? – jontejj

+0

Grazie, ha funzionato per me :) – Niamath

Problemi correlati