On 5 Sep 2006, at 21:18, Fateev, Maxim wrote:

Messages are always put into storage - but they are additionally pushed to subscribers for dispatching. I was going to implement a mixed approach - where consumers that can keep up with the producer will not be impeded by waiting for a poll, but slower/non- active consumers would ultimately rely on a poll from the store.
My view is that this "pushing" functionality should be hidden behind MessageStore API. CachingMessageStore could be created that would keep messages for fast consumers in memory delegating other requests to another permanent MessageStore.
This already happens  - see the Journal Persistence Adaptor.
Having two separate dispatching code paths complicates code.
yes it does - but it's done for performance - polling is slow.

Another problem with direct dispatch is that in case of synchronous dispatch producer performance directly affected by performance of consumer.
The performance of the consumer is currently taken into account whilst dispatching - in the Subscription classes - and the reality is that the producer doesn't always do the dispatching, the thread associated with the consumer does too - if it is slow.

I don't think that it is really a good idea to have receiving socket thread perform write to a consumer socket directly.
This is done for performance - there are defensive mechanisms built in to the transport layers to prevent blocked clients locking the broker - but at the end of the day this is optional - the consumer can decide if messages are dispatched asynchronously from within the broker.

Yes - am changing - so the PendingMessageCursor can in effect ignore new messages from a producer if it is full - or the usage manager has reached it's limit - and poll for them later.
It is an example of two code paths. Only polling part would be required if you eliminate pushing part.
But the two code paths happens currently in PrefetchSubscription

3. getNextMessage(...) should block if there are no messages in a
queue. Otherwise it would require busy polling.
depends on the implementation - more messages available can be triggered from producer etc - providing the PendingMessageCursor is intialized with state and maintains it.
Again blocking getNextMessage() would be much more simple if pushing part is eliminated.
I think you've made the assumption that polling is best ?

4. I'm not sure about semantic of getNextMessage(...,
RecoveryListener) API. Will it create a thread per request? Will
single blocked listener block the whole queue? I think "List
getNextMessage(..., int count)" would have cleaner semantic.
I think a Listener allows for more flexibility - in allowing the PendingMessageCursor to stop a request if the usage memory is at its limit for example
I'm not sure why it has more flexibility. In case of blocking get... call you have the same flexibility but more simple threading. For example you just don't call getNextMessage if the usage memory is at its limit. RecoveryListener would require additional thread for every consumer which doesn't scale.
I don't see why additional threads are required ?
BTW do you plan to have RecoveryListener per queue consumer or single one for the whole queue?

Difficult call - I'm trying not to change the existing code too much
- as I know there's been alot of bug fixes in the PrefetchSubscription/DurableTopicSubscriber etc. code, for timing issues, transactions etc - I'm >>tempted not to loose that if possible :)
You can create different destination implementation that still uses existing Subscription framework but relies on new MessageStore API. I have an example of such code on my desktop.

The comment at the bottom:)

We have tried an implementation of the message store using polling before but the reason we prefer a hybrid approach (which is what we have in essence in ActiveMQ at the moment) - is performance - we get dramatically better performance for push based messaging (the general case) and pulling messages for slower consumers. I think the main difference between the implementation your working on and the current architecture is that currently we can optionally decide to push from the producer socket directly to consumers - which is about as fast as it gets for broker message delivery - and we've taken on the additional complexity to keep this as an option.

But given the flexibility behind the architecture of ActiveMQ - there is nothing to stop having more than one Destination implementation - now that we've incorporated your patch for the DestinationFactory.

cheers,

Rob


Reply via email to