On 3 March 2017 at 09:26, Oleg Kalnichevski <[email protected]> wrote:
> On Thu, 2017-03-02 at 12:23 +0000, Michael Orr wrote:
> > Hi,
> >
> > I'm trying to create a unit test to show that the code we've written
> > around HC is passing in connection pool parameters correctly. I want
> > it to try to get an entry from the connection pool when the pool is
> > already maxed out, and to prove that it will return with a failure
> > within the time that I sent via setConnectionRequestTimeout.
> >
> > I set the 'MaxConnTotal' and 'MaxConnPerRoute' both to 1 on the
> > HttpAsyncClient, then executed two HttpGet methods - the first
> > HttpGet
> > would be to a server URL that would take 10000ms to return, thus
> > using
> > up all connections in the pool for 10 seconds. By using
> > 'setConnectionRequestTimeout(100)' in the RequestConfig I would
> > expect
> > that the second HttpGet would throw a TimeoutException after 100ms.
> > What happens in practice, though, is that it waits the full 10000ms
> > before throwing the TimeoutException.
> >
> > Is this behaviour by design?
>
> Yes, it is (sort of). By default the non-blocking connection validates
> pending connection requests only when leasing or releasing connections.
> If I/O dispatch threads are inactive, like in your example, the
> connection manager does not proactively scans request queue and evicts
> expired requests.
>
> One can force this behavior by using a dedicated monitor thread that
> calls this method at regular intervals (say, every second)
>
> PoolingNHttpClientConnectionManager#validatePendingRequests
>
> This strategy has its cost, though, as it will increase pool lock
> contention under load.
>
> Hope this helps
>
> Oleg
>
>
> > And, if so, how do I force the second
> > HttpGet to throw the error after 100ms?
> >
> > I'm using the following versions:
> > * httpclient-4.5.3
> > * httpasyncclient-4.1.3
> > * httpcore-4.4.6
> > * httpcore-nio-4.4.6
> >
> > The code I'm using is:
> >
> > -------- START CODE --------
> >
> > CloseableHttpAsyncClient client =
> > HttpAsyncClients.custom().setMaxConnPerRoute(1)
> > .setMaxConnTotal(1).build();
> > client.start();
> >
> > RequestConfig requestConfig = RequestConfig.custom()
> > .setConnectionRequestTimeout(100).build();
> >
> > // Request should take ~10000ms
> > HttpGet method1 = new HttpGet("http://localhost:" +
> > SLOW_SERVER_PORT + "/stuff");
> > method1.setConfig(requestConfig);
> >
> > // Request should take ~10ms
> > HttpGet method2 = new HttpGet("http://localhost:" +
> > FAST_SERVER_PORT + "/stuff");
> > method2.setConfig(requestConfig);
> >
> > long lStartTimeMillis = System.currentTimeMillis();
> >
> > Future<HttpResponse> promise1 = client.execute(method1,
> > null);
> > Future<HttpResponse> promise2 = client.execute(method2,
> > null);
> >
> > try
> > {
> > promise2.get();
> > fail();
> > }
> > catch (Exception e)
> > {
> > // Expected
> > long lElapsedTimeMillis = System.currentTimeMillis() -
> > lStartTimeMillis;
> > assertTrue("Took too long to fail", lElapsedTimeMillis <
> > 500);
> > }
> >
> > -------- END CODE --------
> >
> > Thanks in advance,
> >
> > Michael
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]
>
>
Thanks very much for the clarification Oleg!
Best regards,
Michael