Community
Participate
Working Groups
Build Identifier: 20100917-0705 From: Micky Lee Sent: Thursday, February 17, 2011 2:02 PM To: 'JETTY user mailing list' Subject: RE: [jetty-users] Async of HttpClient does not work on Jetty 7.2.2 and 7.3.0? The main different cause this problem occur is in the org.eclipse.jetty.client.SelectConnector.startConnection() method. In this method, it will tune the SocketChannel as blocking or non-blocking. In Jetty 7.1.6, it coded “channel.configureBlocking( false );”, so test code passed. In Jetty 7.3.0, it coded “channel.configureBlocking( true );”, although it turn the channel to non-blocking after channel.connect(), but the point is when channel try to connect to a doesn’t exist ip, it will blocking until timeout. And this is what I didn’t expect. Reference: Jetty 7.1.6: http://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/tags/jetty-7.1.6.v20100715/jetty-client/src/main/java/org/eclipse/jetty/client/SelectConnector.java Jetty 7.3.0: http://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/tags/jetty-7.3.0.v20110203/jetty-client/src/main/java/org/eclipse/jetty/client/SelectConnector.java Sincerely, Micky From: jetty-users-bounces@eclipse.org [mailto:jetty-users-bounces@eclipse.org] On Behalf Of Micky Lee Sent: Thursday, February 17, 2011 12:07 PM To: jetty-users@eclipse.org Cc: 'Victor Liu' Subject: [jetty-users] Async of HttpClient does not work on Jetty 7.2.2 and 7.3.0? Hi all, I need to send async http request to an URL at the same time and I use Jetty HttpClient to test. According to the result log, the Jetty 7.1.6 is able to do correct async but the Jetty 7.2.2/7.3.0 does not. Logs about Jetty 7.1.6: http://tinypaste.com/a7a226 Logs about Jetty 7.3.0: http://tinypaste.com/11a349 Here is the test code @Test public void asyncConnectInvalidFuture() throws Throwable { HttpClient httpClient = new HttpClient(); httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); httpClient.setConnectTimeout(10 * 1000); try { httpClient.start(); for (int i = 0; i < 4; ++i) { HttpExchange exchange = new HttpExchange(); exchange.setMethod("GET"); exchange.setURL("http://192.168.99.99"); exchange.setRequestHeader(HttpHeaders.CONNECTION, HttpHeaderValues.KEEP_ALIVE); httpClient.send(exchange); } } catch (Exception e) { e.printStackTrace(); } synchronized (this) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } Should notice that the IP 192.168.99.99 does not exist, so it must get timeout exception. In the correct async scenario, the 4 requests should be sent at the same time and they timeout almost at the same time as Jetty 7.1.6 logs described. But the Jetty 7.3.0 does not use the scenario, according to the logs, it sends first request and waits for timeout, then sends the second request and so on. So we see the logs just 10 seconds after another request by each. I doubt HttpClient asynchronous function when this scenario. Why 7.1.6 is OK and 7.2.2/7.3.0 NOK? Is this a bug? Sincerely, Micky Reproducible: Always Steps to Reproduce: 1. use a IP which does not exist 2. run HttpClient async mode to request to this IP 3. the request will be blocked until timeout, then the next request will be processed
Simone, Did you/we change HttpClient connection to be blocking? If so, does that explain this difference?
Greg, you changed the relevant code in revision 2189 with the comment "314087 Simplified SelectorManager", I think on the verge of the discussion we had about simplifying the handling of initial connection management in the selector. The main point of this trickery is that it is difficult to implement connect timeouts for channels in non blocking mode. The only way is to submit a scheduled task that expires and checks if the connection is established. Prior to your change I was submitting an instance of inner class SelectConnector.ConnectTimeout to a timer to implement connect timeouts. This class is still present in the current sources but now it's unused. Perhaps you can obtain the same effect by changing line 143 from: channel.connect(address.toSocketAddress()); to channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout()); I do not think that the SO timeout is affecting the connect timeout, but only the read timeout, so the current code is ineffective (and explains why Socket.connect() takes a connect timeout parameter). If you have further insights, comment here, otherwise I am going to fix this using the 2-parameter connect() method as above.
I think having the timeout will help somewhat, but it will not help with the scenario reported, where 4 connections to non existent hosts want to be attempted in parallel. I'll have a look a re-enabling an async connect - at least as an option.
r2809 I readded the async connect mode, but it is now optional, so you need to do a httpclient.setAsyncConnect(true) It would be great if you could try this out from source or snapshot before we do a release.
Greg, the blocking connect functionality was already present in SelectConnector but never used because SelectConnector is package private (so user code cannot cast to it and configure the blocking of the connects). I removed that code from SelectConnector since now you added the same functionality in HttpClient, and renamed from "asyncConnects" to "connectBlocking" like it was in SelectConnector, and updated the code accordingly.
Excuse me, I want to know if there is a patch for it? Or I just need to checkout the source code from SVN and build it by myself?