2012-05-29 24 views
6

Usiamo Apache Camel come motore di orchestrazione. In genere, il seguente scenario:Apache Camel: perché la connessione TCP non è chiusa dopo aver ricevuto 200 OK

client invia richiesta HTTP < -> codice CAMEL < -> server esterni (s)

La palla inizia a rotolare quando il nostro client invia una richiesta HTTP al nostro codice CAMEL. Il codice Camel attiverà server esterni tramite le chiamate HTTP REST. Alla fine, il codice Camel invierà una risposta al cliente.

L'ultima azione prima di inviare la risposta al client, il codice Camel invia un GET HTTP verso un server esterno. Quindi viene prima impostata una connessione TCP, quindi i dati inviati. Dopo un po 'di tempo (questo potrebbe richiedere da 5 a 10 secondi), il server esterno risponde con 200 OK.

Problema: Camel non invia TCP FIN al server esterno dopo aver ricevuto 200 OK. Di conseguenza, la connessione TCP rimane aperta ... (il server esterno chiude quindi la connessione TCP stessa dopo un timeout di 200 secondi, ma ciò significa che una risorsa TCP viene persa durante 200 secondi).

Quindi, a livello TCP, va in questo modo:

Camel < ----------> server esterni

TCP SYN --> 
    <-- TCP SYN,ACK 
    TCP ACK --> 

    HTTP GET --> 
    <-- 200 OK 
    TCP ACK --> 

    <200 seconds later> 
    <-- TCP FIN,ACK 
    TCP ACK --> 

Qualsiasi idea di come posso avere Camel chiudere il Connessione TCP dopo aver ricevuto il 200 OK?

Nota: ho provato ad aggiungere l'intestazione "Connessione: chiusa", ma Camel non ha aggiunto l'intestazione?! Sembrava di ignorarlo ...

questo era il codice per aggiungere l'intestazione:

exchange.getOut().setHeader("Connection","Close"); 

Sto usando Camel 2.9.1 in un quadro primavera con Eclipse IDE.

+0

Quale componente http Camels usi? –

+0

Ciao, sto usando Camel 2.9.2 (non 2.9.1 come ho detto prima :() e camel-http-2.9.2.jar (e commons-httpclient-3.1.jar). – opstalj

+0

Puoi riprodurre questo comportamento con qualsiasi server HTTP? O il server del client è l'unico che non chiude la connessione? –

risposta

4

Sfortunatamente, non ho visto un'altra soluzione che creare una classe HttpHeaderFilterStrategy personalizzata che non filtra l'intestazione di Connection. Quindi prima di inviare la mia richiesta al server esterno, sto impostando l'intestazione "Connection: close". Appena questa richiesta viene risposta, il codice Camel invia quindi un TCP FIN, ACK per chiudere la connessione TCP.

Maggiori dettagli:

1) Creare una classe HttpHeaderFilterStrategy personalizzato, ad esempio: CustomHttpHeaderFilterStrategy

2) modificare l'applicationContext.xml in modo che punti a quella classe, ad esempio:

<bean id="http" class="org.apache.camel.component.http.HttpComponent"> 
    <property name="camelContext" ref="camel"/> 
    <property name="headerFilterStrategy" ref="myHeaderFilterStrategy"/> 
</bean> 

<bean id="myHeaderFilterStrategy" class="com.alu.iptc.com.CustomHttpHeaderFilterStrategy"> 
</bean> 

3) adatta il tuo codice, in modo che la connessione: intestazione vicina è impostata, ad esempio:

exchange.getOut().setHeader("Connection","close"); 
1

Le connessioni HTTP1.1 devono essere considerate mantenute attive dopo il primo messaggio per un po 'per consentire la consegna di più file in una sessione TCP per motivi di prestazioni. Normalmente, un server http potrebbe interrompere le connessioni dopo alcuni secondi per salvare i thread e consentire il download di più file. Il componente http Camel probabilmente si comporterà allo stesso modo. http://en.wikipedia.org/wiki/HTTP_persistent_connection

Il client HTTP ufficiale che Camel si basa sulla può essere configurato per usare o non usare connessioni persistenti, ma di default è vero: http://docs.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html

Anche se non ho provato, dovrebbe essere possibile impostare un proprietà di sistema per configurare questo

http.keepAlive=<boolean> 

si dovrebbe essere in grado di impostare sul contesto cammello, se si desidera

<camelContext> 
    <properties> 
     <property key="http.keepAlive" value="false"/> 
    </properties> 
</camelContext> 

Nota che non l'ho provato. Se lo fai funzionare, sarebbe bello sentire i risultati!

+0

Peccato, l'ho provato ma non sembrava avere alcun effetto ... Ci dovrebbe essere un modo per dire all'applicazione Camel che tutte le informazioni richieste sono state ricevute e quindi la connessione TCP può essere chiusa, giusto? – opstalj

+0

prova a impostarla come proprietà di sistema allora. Il client HTTP4 in Java dovrebbe rilevare questo. –

+0

Potrebbe essere la differenza: sto usando la pianuraComponente HTTP e non quello HTTP4 ...? – opstalj

Problemi correlati