From: <ovi...@jb...> - 2005-05-05 21:08:34
|
The code that's currently in CVS does not block the server thread while the client processes the message, but also does not correctly handle acknowledgment (i.e. CLIENT_ACKNOWLEDGMENT, etc.) However, the goal was to first have the infrastructure in place so we can write test and stress cases and fine tune the behavior later. This is how I see things happening. While reading the explanations, please refer to the diagram http://wiki.jboss.org/wiki/attach?page=JBossMessagingDesignDiagrams%2F2004.05.05_Consumer+Acknowledgment.jpg, which presents a simple use case of a topic with only one consumer. Message M1 is delivered by a core thread to the topic (1). A topic is made of a LocalPipe and a PointToMultipointRouter. The LocalPipe first attempts synchronous delivery, the router synchronously pushes M1 to the Consumer C1, which invokes handleCallback() on its callback handler (2). The remoting layer forwards the message, which eventually is delivered to the MessageCallbackHander on the client side. In a colocated configuration, M1 is delivered to the MessageCallbackHandler by the core thread itself. In a remote configuration, the core thread blocks waiting the remote call to complete. The MessageCallbackHandler accepts M1 by queuing it in a in-memory staging area (currently it is called RendezVous, but this is a bad name, it will change; a more appropriate name I think would be ClientDeliveryQueue) and immediately releases the tread, which is either the remoting thread or the core thread, depending on the configuration (3). This is very fast, it does not block the server thread for long and also not much can go wrong here since there is no client code involved. M1 is not acknowledged, however. When the Consumer's callbackHandler.handleCallback() completes (4), the Consumer NACKs the message to the topic, which makes the topic to store the message M1 in the MessageStrore and the NACK (C1-M1) in the AcknowledgmentStore (5). The storage can be reliable (persistent store) or unreliable (memory). Independently of this process, on the client side, a client thread (the tread that invokes MessageConsumer.receive() or a thread that polls the RendezVous and calls into listener, if any) consumes M1 (6) and sooner or later produces the positive acknowledgment (7), which is sent over remoting to the Consumer with a direct synchronous call. The Consumer accesses the AcknowlegmentStore (8) and removes the M1-C1 NACK which triggers M1 removal from the MessageStore, if there aren't any other NACKs for M1. This are several interesting particular cases worth commenting on: 1. What if the client never acknowledges? After a while, the topic will redeliver M1 and the process repeats until message's time to live expires. 2. What happens if a message is redelivered before the client acknowledges it? There two cases: if the message is still in the RendezVous, it is simply ignored. However, this situation is possible: the message is taken out of the queue (step (6)) and while the acknowledgment is being sent to the Consumer (7), an independent re-delivery puts it back in the queue (3). This means duplicate delivery. 3. What if RendezVous fills up? There should be a limit of some sort, after which the RendezVous won't even accept messages. From the server side, nothing changes, messages are NACKed as before and go to the store. View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3876680#3876680 Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=3876680 |