On 6 March 2015 at 02:16:34, tfasz (
tod...@gmail.com) wrote:
> Couple of questions:
> - Is there a way to know the connection or channel is blocked before
> publish? I tried adding a BlockedListener on the connection,
> but it only seems to notice the blocked connection after an attempt
> to publish so I always end up with at least one blocked thread.
Connections are only blocked when they attempt to publish (when RabbitMQ
sees a basic.publish frame or content frame or body frame on it). We do not
want to block consumers who drain queues and thus relieve RAM and disk space
pressure.
This is why you only see connection blocked listener fire when you attempt
to publish: connection is not blocked prior to that.
> - I tried to implement your suggestion of using channel.abort()
> and interrupting the blocked thread but it looked to exhibit
> the same behavior. Do you have an example I could look at to see
> if I am doing something wrong?
So if you try to interrupt the thread that's blocked in a socket write, an InterruptedException
is not thrown? Things may be better with NIO, to which we plan to migrate after 3.5.0, but
I cannot guarantee that without trying.
> I really think you should reconsider the current design that
> can block a calling thread forever. This is a bad failure scenario
> waiting to happen.
This is not intentional design. We *do not* block caller threads in
the library. Socket#write does, because local TCP buffer fills up when RabbitMQ
stops reading from the socket (which is how blocking is implemented).
As I've mentioned before, there is no good
solution since RabbitMQ stops reading from the socket for blocked connections.
It therefore won't notice that the channel was closed if we just "abandon" a Channel instance
and find a way to unblock. Which leads to inconsistent state in the server and client.
> Couple of alternatives:
> - Allow someone to configure an optional timeout on channel.close().
> If a timeout occurs we could then take additional action such
> as trigger a connection.close().
RabbitMQ does not read from the socket that belong to closed connections.
connection.close then won't be seen.
> - Allow the client to be configured so it will auto-disconnect
> the whole connection if in a blocked state for longer than some
> duration. Raise exceptions on channels in a blocked state.
See above. You can only close TCP connection (which may be sufficient).
> - Have the client library internally buffer messages in a queue
> and publish on a different thread (this is how the spymemcached
> client library works).
Again, what would that solve the peer does not read from the socket?
TCP buffers would fill up quickly and any write(2) call will block.
> Obviously we can implement this too but
> it seems like a client library should implement this if it is always
> required.
I'm afraid it won't be easy to implement this, for you or for us, although
switching to NIO may provide a solution. I hope now it's a bit clearer what the hard parts are.