[ Apache Camel: why is TCP connection not closed after receiving 200 OK ]
We are using Apache Camel as an orchestration engine. Typically, the following scenario:
client sends HTTP request <-> CAMEL code <-> external server(s)
The ball starts to roll when our client sends a HTTP request to our CAMEL code. The Camel code will trigger external servers via REST HTTP calls. Eventually, the Camel code will send a reply back to the client.
The last action before sending the response back to the client, the Camel code sends a HTTP GET towards an external server. So a TCP connection is setup first, then the data sent. After some time (this might take up 5 to 10 seconds), the external server replies with a 200 OK.
Problem: Camel does not send a TCP FIN to the external server after receiving the 200 OK. As a result, the TCP connection remains open ... (the external server then closes the TCP connection itself after a timeout of 200 seconds, but this means a TCP resource lost during 200 seconds).
So, at TCP level, it goes like this:
Camel <----------> external server
TCP SYN -->
<-- TCP SYN,ACK
TCP ACK -->
HTTP GET -->
<-- 200 OK
TCP ACK -->
<200 seconds later>
<-- TCP FIN,ACK
TCP ACK -->
Any idea how I can have Camel close the TCP connection after it has received the 200 OK ?
Note: I tried adding the "Connection: close" header, but Camel did not add the header ?! It seemed to ignore it ...
This was the code to add the header:
exchange.getOut().setHeader("Connection","Close");
I am using Camel 2.9.1 in a Spring framework with Eclipse IDE.
Answer 1
Unfortunately, I did not see another solution than create a custom HttpHeaderFilterStrategy class which does not filter out the Connection header. Then before sending out my request to the external server, I am setting the header "Connection: close". As soon as this request gets replied, the Camel code then sends a TCP FIN, ACK in order to close the TCP connection.
More details:
1) create a custom HttpHeaderFilterStrategy class, eg: CustomHttpHeaderFilterStrategy
2) adapt the applicationContext.xml so it points to that class, eg:
<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) adapt your code, so that the Connection: close header is set, eg:
exchange.getOut().setHeader("Connection","close");
Answer 2
HTTP1.1 connections are to be considered to be kept alive after the first message for a while to allow multiple files to be delivered in one TCP session for performance reasons. Normlly, a http server might cut connections after a few seconds to save threads while allow multiple files to be downloaded. The Camel http component will probably behave the same way. http://en.wikipedia.org/wiki/HTTP_persistent_connection
The official HTTP client which Camel relies on can be configured to use or not use persistent connections, but default is true: http://docs.oracle.com/javase/1.5.0/docs/guide/net/http-keepalive.html
Although I have not tried it, it should be possible to set a system property to configure this
http.keepAlive=<boolean>
You should be able to set it on the camel context if you want
<camelContext>
<properties>
<property key="http.keepAlive" value="false"/>
</properties>
</camelContext>
Note that I have not tried it. If you make it work, it would be nice to hear the results!