I read here that EntityUtils.consume(httpEntity)
will result in releasing the connection back to the connection pool, but when I looked at the source code, I couldn't understand how is that happening. Can someone please point me to the part of the code where EntityUtils.consume(httpEntity)
or EntityUtils.toString(httpEntity)
is releasing the connection when using the low level Elastic Search Rest Client
?
What happens to the connection if there is a SocketTimeoutException
and I don't consume the HttpEntity
?
Client-side close and connection release to the Pool (steps)
EntityUtils.consume
&EntityUtils.toString
> the first one willclose()
theinstream
if it fully consumes the entity. The second one will always callinstream.close()
in its finally clause.instream
is the name given to the InputStream variable.instream
.close()
> For this example, the implementation of theInputStream
is aContentInputStream
. Theclose()
method forces theContentInputStream
to be read till its end by the loop mechanism shown in the code snippet.Following calls to this stream will lead to an
EOF
exception.Pool
> Checks all pooled resources status. This operation may be triggered by some actions (as a new request), or may be managed by underlying threads. If one resource/stream was closed by the other end, it will get anEOF
exception (as the buffer was forced to advance to the end). The spot is marked as invalid.Pool
> All invalid spots are recycled. It will remove the closed streams and create new ones, or restore the existing ones without the need of erase+create (depending on the resource type). This means the spot that was holding the stream is avaliable again, with a new stream ready to be used:The connection is released back to the pool. The other end is not using it anymore, so the pool has total control of it. Now the pool is allowed to erase it, restore it, and assign it to another requester..
Example
Let's imagine a
Pool
that manages 3 resources, such asHttpConnections
. You already have 3 threads using this pool, so the spots are all occupied.Meanwhile
ThreadZ
waits for a connection to be released back to the PoolThreadA
finished its job and closes its connection. ThePool
will notice this when the status of thePoolEntry
is closed. DifferentPoolEntry
implementations will check this is different ways, one of them being getting anEOF
exception while trying to read from a stream. Other implementations could have different mechanisms to check if the resource is closed. If thePoolEntry
tells that his resource is closed/invalid, thePool
will recycle this spot. There are two options here:a) Erase and create.
b) Restore.
"Releasing the connection back" could be translated to "now there's an avaliable spot/resource again". The pool can now give a connection to
ThreadZ
:consume
/toString
- connection releaseAll explained above means that calling
close()
in theInputStream
will trigger the connection release.This happens both in
consume
(if the entity content is fully consumed) andtoString
methods:What happens to the connection if there is a SocketTimeoutException and I don't consume the HttpEntity?
As you notice, both methods throw an
IOException
, andSocketTimeoutException
is inherited from it. It is responsability of the caller to catch this exception and manage to close all resources if such scenario happens. For example:Notice that if a
SocketTimeoutException
is thrown, specificPoolEntry
implementations could also check if the resource is invalid without the need of aclose()
call. Usingclose()
guarantees that thePool
will recycle the spot after a correct use of it, and can be used as well as a "invalid marker" when you are able to catch a thrown exception.But specific
Pool
implementations will be able to also check if a resource is invalid even if an uncatchedException
didn't let you specifically callclose()
, as they would be able to check the status with different mechanisms. For example, checking how many time a connection was inIDLE
state. If this time is superior to a certain treshold marked by thePool
, this spot will be recycled without the need of a previousclose()
call from the client.This time the
Pool
will be the end that callsclose()
on it, avoiding a possibledeadlock
in the client side, if this one doesn't manage the max connection time or certain exceptions.