Bottom Line: I'm trying to understand if ColdFusion is able to make use of a persistent http connection outside of a single request via the CFHTTP tag. Some of this post is "what have I found/tried."
My system: CF10 IIS7.5 Windows 7
I am currently hooking into ElasticSearch via an HTTP Rest interface which will have a magnitude of cfhttp calls. In this case, ColdFusion is the Client and ElasticSearch is the server. As recommended, I passed the keep-alive header along with the cfhttp request, but found the CFHTTP seemed to always add a close right after it resulting in this header:
<!--- Calling tag --->
<cfhttp url="loc.mysite.com?endpoint"
method="POST"
result="ret">
<cfhttpparam type="HEADER" name="Keep-Alive" value="300">
<cfhttpparam type="HEADER" name="Connection" value="keep-alive">
<cfhttpparam type="xml" value="#body#" />
</cfhttp>
<!--- Results in this header. (dumping getHTTPrequestdata() on a dummy page) --->
connection: keep-alive,closed
First, I cannot figure out how to prevent the close from occurring.
Second, I cannot figure out if ColdFusion would reuse the connection, even if it is sent without the close during the same request or outside of this request. Clearly this has to do with how Java is interacting with the OS at this point. Initially, I thought it would be handled by the magic of ColdFusion, but I'm beginning to think that it is not using any of the fancy Java pooling magic.
Third, I cannot find any documentation on http connection pooling in ColdFusion. It does DB connection pooling just fine, but http pooling is probably a relatively new requirement.
Fourth, I have found the CFX_http5 is still working in ColdFusion 10 with Tomcat (what are the chances). While it is good at multithreading requests, there is little mention of how the keep-alive is used. Without purchasing it, I can't test it inside a loop. It does not add the close header. It sends keep alive as I would expect.
Sixth (edited heavily since initial post) Sixth, Windows has a default number of temporary or "ephemeral" ports that it can make use of to spawn new outbound TCP connections. By default, once a connection is opened, Windows will keep it alive for two minutes (although it's just abandoned and taking up space at this point). This is a TCP configuration, so http headers aren't directly at play here. The default number of ports available is 5,000 less 1024 = 3076 ports. This means all ColdFusion instances on a box could make up to 3076 http requests in any given two minute window without being choked waiting on an available connection port. If too many requests are flooded (I have no idea at what point), you will receive a "connection closed" error. This reminds me of garbage collection at a primitive level. So, up the level in the registry (see post) below and you avoid these chokes, but you are still experiencing connection setup/tear down delays and this solution will not scale.
Update: CFX_HTTP5 does support keep-alive and persistent connections as expected within a single ColdFusion request. My 150K query test to my ElasticSearch endpoint previously ran in 15 minutes. With CFX_HTTP5, it ran in 4 minutes. In addition, I was able to switch the registry back to the default number of ports. The next step is to figure out if HTTPComponents will work. I have that nearly working.
Update 2:: Built out a custom http call using the HTTPcomponents suggested below. I used a basic connection pool manager with default settings. I have not attempted to tune it yet. The process finished in 5 minutes which is a tad slower than cfx_http5, but still a lot faster than cfhttp. In addition, I have not done tests involving multiple ColdFusion requests to really test the connection pool.
Update 3: I verified that HTTPComponents is indeed setting up a proper connection pool. However, with this comes a responsibility to properly manage those connections and the pool itself to ensure it is a good steward of system resources. I was able to run several million HTTP requests from several different simultaneous requests while only opening a small handful of HTTP connections. From the logs, I was able to see how many connections were being used, idle, or spun-up. It's really not that much code either, the people behind the project have great documentation.
HTTPComponents Connection Pool:
Single request, unlimited CFHTTP to same connection = single open TCP connection
N-requests = <N open TCP connections.
CFHTTP
N-CFHTTP calls + N-CFHTTP calls in previous 60 seconds = open TCP connections
Reference: I did find that Java has this available, which shows that it's in the realm of possibility, but who knows how Adobe has implemented CFHTTP Persistent Http client connections in java
CFX_http5 custom tag uses C++ for custom http connections, so it's possible that it understands connection pooling. http://www.cftagstore.com/tags/cfxhttp5.cfm
A related question: Maintain Outbound TCP Connection Pool in ColdFusion
About Windows Max Connections/Ephemeral ports http://kb.globalscape.com/KnowledgebaseArticle10438.aspx
HTTP has a persistent connection function that allows the channel to remain open rather than be closed after a requested exchange of data. TCP is a connection-oriented protocol: It starts a connection after confirmation from both ends that they are available and open to a data exchange.
There are several advantages of using persistent connections, including: Network friendly. Less network traffic due to fewer setting up and tearing down of TCP connections. Reduced latency on subsequent request.
Non-persistent and persistent are the two types of HTTP connections used to connect the client with the webserver. The non-persistent connection has connection type 1.0 , while the persistent connection has connection type 1.1 .
Persistent connection means that a single TCP connection can be used for multiple HTTP requests. This eliminates the need to set up many TCP connections. Pipelining means that a client can send an arbitrary number of requests over a TCP connection before receiving any of the responses.
I'm 99% sure that CFHTTP does not support persistent connections, it's just not set up to deal with it. I think really you'll need a different API to handle both the connection and individual requests. I've not got CF10 to hand, but CF9 has a version of HTTPClient from 2001, so I hope the CF team updated with CF10!
I would look to use a Java-based HTTP library, such as HTTPClient. From the Features list: "Connection management support for use in multi-threaded applications. Supports setting the maximum total connections as well as the maximum connections per host. Detects and closes stale connections"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With