You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@rocketmq.apache.org by Rick Zhang <zh...@gmail.com> on 2017/02/02 00:12:51 UTC

An new version of RocketMQ-JMS

As discussed before [0], recently I have pushed a new branch named
"newversion" onto github [1]. This version tries to follow the JMS
hierarchy abstract model from the beginning. The model is the foundation
that other JMS features are built on. Therefore, I am trying to introduce
my understanding of this model and each layer's responsibility shortly, and
then illustrate how to follow it as much as possible using RocketMQ-Client
without changing any RocketMQ-Client code.


*The main conceptions of JMS Spec abstract model:*

1. Connection refers to a network connection to JMS-Provider Broker, and
controls messages produce and consume. After a connection object is
created, the network connection has been established, and when this
 connection starts, message deliveries of it begin to work. A connection
equals to a JMS-Client, and for broker, this client is identified by the
term "client identifier".

2. Session is a factory to create producer/consumer, and is a
single-threaded context that concurrent access is prohibited. Producers and
consumers created by a session are restricted to use serially and orderly.
Transaction is also defined in session scope. In other words, in JMS Spec
opinion, session is designed a single thread to avoid too much complexity.
If client hope to work more efficient, multi sessions should be used.

3. Message delivery is an implicit layer paralleling with consumer. When
connection stops, message delivery should be stop immediately, but the last
message may be still consuming. Message delivery like a pipeline whilst
consumer like a executor. Once message delivery is turn off, only existing
messages could be consumed.

4. Producer/Consumer are the real executors, and them created from the same
session should send and consume serially and orderly. Both synchronous and
asynchronous consume should be supported.
Share,non-share,durable,non-durable consume patterns should be supported
too.
    "SubscriptionName" and "Client Identifier" is used to decide whether
each message is consumed by only one consumer in this group or copy is
delivered to every consumer, just like  the term "ConsumeGroup" in
RocketMQ.
    Multi acknowledge model should be supported, and message selector could
be used to filter messages when consume.

    There are lots of features defined in JMS Spec, such as many message
header/property fields(MessageID,Redelivered,Expiration,Priority and so
on), request/reply,TemporaryQueue,Duplicate message
produce/consume,transaction. They are based on the hierarchy abstract
model, and following this model is the beginning of developing a new JMS
implement.



*How to match the model by RocketMQ-Client*

1. Connection maintains an MQClientInstance inside, which means a
connection object refer to a client's active connection to RocketMQ Broker.
All session/producer/consumer created from this connection will share the
MQClientInstance. More specifically, the same "instanceName" is used
through a connection and its creation's lifecycle.

2. RocketMQ Pull model is adopted, because we hope to control consume
behavior more accurate,such as consume time point, begin offset. For
example, "non-durable" consume model will only consume messages delivered
after the consume start. To achieve this target, we would fetch the max
offset of ConsumeQueue and start to pull message from that position
regardless of last consume offset.

3. Message delivery is explicitly separated from consumer, in order to
control delivery more flexible. Each consumer has its own message delivery
service to distinguish their consume destination/offset/messageSelector.
But pulled messages are executed by a single thread service owned by this
consumer's session. After message has been consumed(async-model) or
received(sync-model), acknowledge will be sent to broker automatically.

4. Synchronous and Asynchronous consume are both being supported well.
Share/non-share consume patterns are implemented by RocketMQ
"ConsumeGroup", whilst durable/non-durable are implemented by appointing
different offset when pulling.

As a whole, we could find similar conceptions of
connection/producer/consumer/queue/topic in RocketMQ, and most of their
functionalities could be implemented by means of some variation. But
session and its single-thread model are not so easy to implement.

I really appreciate that you could give me some advice on any aspect.


[0] - The discuss about refactoring current DefaultXXX implement
https://github.com/rocketmq/rocketmq-jms/issues/6
[1] - https://github.com/rocketmq/rocketmq-jms/tree/newversion

Thanks,
Rick Zhang