Quarkus: how to use point-to-point messaging with Artemis? - quarkus

I am using quarkus version: 1.5.2.Final and the following dependency to include reactive messaging (I have a running docker instance of Artemis in between the sender and receiver project):
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-reactive-messaging-amqp</artifactId>
</dependency>
On the sender project I have a #Outgoing('stock-quote') annotation on a method that produces a random number every second and returns Flowable<Message<String>>. The configuration is as follows:
mp.messaging.outgoing.stock-quote.connector=smallrye-amqp
mp.messaging.outgoing.stock-quote.address=stocks
mp.messaging.outgoing.stock-quote.durable=true
On the receiver project the receiver is located which has a method with the annotation #Incoming('stock)'. The configuration is as follows:
mp.messaging.incoming.stocks.connector=smallrye-amqp
mp.messaging.incoming.stocks.durable=true
What do I notice? Everything works as it should. When the receiver project goes down for whatever reason, the messages that are still being sent by the sender are persisted, which is good. However, when the receiver comes back online again, the receiver does not receive the persisted messages, instead it starts on a separate 'client thread'. The persisted messages just stay there.
I tried to also add the #Broadcast annotation on the sender side. Since I also want that there are multiple instances of receiver, so the messages are being divided over the receivers. Then, when a receiver goes offline, the messages are being persisted again. When the receiver comes back up it gets the new messages being sent, but the persistent messages just stay there (in another 'client thread', and worse, the persistent messages on this 'client thread' are accumulating (due to the broadcast).
So what do I want? I want that there is a sender that sents messages. These messages are being divided over two or more receiver instances. If one receiver goes down, the messages are being taken care of by the other instances. If all the receivers are down, the messages are being persisted, and once there are one or more receivers online again, these persisted messages are being processed. So basically I want this:
Anyone has any idea on how to do this with quarkus reactive messages in combination with artemis?

Related

Is AMQP's DistributionMode analogous to autoacknowledge in Tibco?

We are migrating from Tibco to start using ActiveMQ Artemis. There are several ack settings that are available on Tibco, but we haven't found anything that's simply similar to this in Artemis. We are using the amqpnetlite .NET library to interface with Artemis, and as part of our code using DistributionMode to either move or copy based on the boolean value we are assigning to a configuration flag that we are calling as UseAutoAcknowledge. I haven't found much documentation about DistributionMode but for one that isn't very clear here - http://docs.oasis-open.org/amqp/core/v1.0/amqp-core-messaging-v1.0.html.
My question is if DistributionMode is set to move - does Artemis send an acknowledgement to the client and doesn't when it is set to copy?
I can't talk to Tibco but I can try to explain AMQP DistributionMode. Essentially the DistributionMode is a setting as to the behaviour of the receiver - a receiver with a move mode is expecting the messages to be sent only to it, not to other receivers - this is the normal behaviour of a consumer on a queue. A receiver with a copy mode is expecting other receivers to also receive the message (like a queue browser, or - sort of - like a subscriber to a topic). In a traditional Client-Broker topology, the DistributionMode is only really interesting when receiving messages from the Broker, and is unlikely to have effect when sending messages to the Broker.
Acknowledgement is separate from the DistributionMode. AMQP has the concept of Disposition which is similar to but not the same as Acknowledgement. Disposition is ultimately the action that the sender will apply at the completion of the message transfer (and so interacts with DistributionMode for messages sent by the Broker). Conceptually for each message transfer a Broker might decide that the transfer has completed successfully; that it has failed - but in a way that retrying might succeed; that it has failed in a way that will not succeed on retry; or some other more subtle outcome. Here the behaviour at the Broker is probably different depending upon whether the DistributionMode was move or copy (the specification left this vague to allow flexibility in implementations). If the receiver is asking for messages to be moved, and it declares that the transfer was unsuccessful, a broker is likely to make that message available for all competing consumers. If the receiver was asking for copy, then it never held an exclusive lock on the message, and so the choice is only whether to retry sending the copy to that same consumer.
Perhaps the simplest thing here is if you can describe the behaviour that you desire, and experts on Apache Artemis can weigh in on if/how that can be achieved.

MassTransit - publish to all consumer instances

I am looking for a way for each consumer instance to receive a message that is published to RabbitMQ via MassTransit. The scenario would be, we have multiple microservices that need to invalidate a cache on notification. Pub-Sub won't work in this instance as there will be 5 consumers of the same type as its the same code per service instance, so only one would receive the message in a traditional PubSub.
Message observation could be an option but this means the messages would never be consumed and hang around forever on the bus.
Can anyone suggest a pattern to use in the context of MassTransit?
Thanks in advance.
You should create a management endpoint in each service, which could even be a temporary queue (just request a receive endpoint without a queue name and one will be dynamically generated). Then, put your queue invalidation consumers on that endpoint. Each service instance will receive a unique instance of the message (when Publish is called), and those queues and bindings will automatically be removed once the service exits.
This is exactly how the bus endpoint works, but in your case, you're creating a receive endpoint which can have consumer message type bindings, so that published messages are received, one copy per service.
cfg.ReceiveEndpoint(cfg => { ... });
Note that the queue name is not specified, and will be automatically generated uniquely.

MassTransit3 how to make request from consumer

I want to make a req/res request from IConsumer.Consume() method, but I don't see any method on ConsumeContext<> that returns a reference to IRequestClient<,>. Do I need to hold a reference to IBusControl somewhere and use it or I can use context somehow?
In this case, it is best to create the request client outside of the consumer and pass it as a dependency to the consumer as an IRequestClient<,> interface. The request client is created with IBus, which is outside of the consumer context.
It also ensures that the request will be less likely to deadlock with the broker because responses are received on the bus endpoint, and not the receive endpoint of the consumer (which, if you had a concurrency limit of 1, would never finish).
It's also not possible to connect consumers to a started receive endpoint, which is a requirement of the request/response handling (it happens under the covers). The bus, however, can connect consumers for messages which are sent (responses are sent to the bus address, versus being published) which is why it is used for responses to the requests.
To keep message tracking continuous, it may be nice to set the InitiatorId on the outbound request to the CorrelationId of the consumer message, as well as copying the ConversationId. This helps with tracing and keeping track of the overall message command/event flow.

JMS consumer inside a Netty handler?

I'm designing a quite complicated system and was wondering what the best way is to put a jms consumer (activemq, vm protocol, non persitent) inside a netty handler.
Let me explain, i have several clients connecting to my netty server using websockets. For every client connection i create a jms consumer that listens for interesting messages on one or more topics. If a interesting message arrives i need to do a extra step (additional filtering) before sending the message to the client using the websocket.
Is the following a good way to do this:
inside a SimpleChannelInboundHandler i declare a private non static consumer
the consumer is initialized in channelActive
the consumer is destroyed in channelInactive
when a message is received by consumer i do the extra filter a send it using ctx.channel().write()
In this setup i'm a bit worried that the consumer might turn into slow consumer and slow everything down, cause the websocket goes over the internet.
I came up with a more complex one to decouple the "receiving of message by consumer" and "sending of message through a websocket".
inside a SimpleChannelInboundHandler i declare a private non static consumer
the consumer is initialized in channelActive
the consumer is destroyed in channelInactive
when a message is received by consumer i put it in a blockedqueue
every minute i let a thread (created for every client) look in the queue and send the found messages to the client using ctx.channel().write().
At this point i'm a bit worried about the extra thread per client.
Or is there maybe a better way to accomplish this task?
This is a classic slow consumer problem and the first step to resolving it is to determine what the appropriate action is when a slow consumer is detected. If it is acceptable that the slow consumer misses messages then the solution is some variation on dropping messages or unsubscribing them from the feed. For example, if it's acceptable that the client misses messages then, when one is received from JMS, check if the channel is writable. If it isn't, drop the message. If you want to give yourself a bit more of a buffer (although OS buffers are quite large) you can track the number of write completion future's that haven't completed (ie the messages haven't been written to the OS send buffer) and drop messages if there are too many outstanding write requests.
If the client may not miss messages, and is consistently slow, then the problem is more difficult. One option might be to divert messages to a JMS queue with a specific header value, then open a new consumer that reads messages from that queue using a JMS selector. This will put more load on the JMS server but might be appropriate for temporary slowness and hopefully it won't interfere with you main topic feeds. Alternatively you might want to stash the messages in a different store, such as a database, so you can poll for messages when they can be sent. If you do this right a single polling thread can cope with many clients (query for clients which have outstanding messages, then for each client, load a bunch of messages). However this isn't as convenient as using JMS.
I wouldn't go with option 2 because the blocking queue is only going to solve the problem temporarily, and you can achieve the same thing by tracking how many write operations are waiting to complete.

About JMS system structure

I’m writing a server/client game, a typical scenario looks like this: one client (clientA) send a message to the server, there is a MessageDrivenBean in server to handle such messages. After the MDB finished its job, it sends the result message back to another client (clientB).
In my opinion I only need two queues for such communication, one for input the other for output. Creating new queue for each connection is not a good idea, right?
The Input queue is relative clear, if more clients are sending message at the same time, the messages are just waiting in the queue, while there are more MDB instances in server, that should not a big performance issue.
But on the other side I am not quite clear about the output queue, should I use a topic instead of a queue? Every client is listening the output queue, one of them gets the new message and checks the property to determine if the message is to it, if not, it rollback the transaction, the message goes back to queue and be ready for other client … It should work but must be very slow. If I use topic instead, every client gets a copy of the message, if it’s not to it, just ignores the message. It should be better, right?
I’m new about message system. Is there any suggestion about my implementation? Thanks!
To begin with, choosing JMS as a gaming platform is, well, unusual — businesses use JMS brokers for delivery reliability and transaction support. Do you really need this heavy lifiting in a game? Shouldn't you resort to your own HTTP-based protocol, for example?
That said, two queues are a standard pattern for point-to-point communication. Creating a queue for a new connection is definitely not OK — message-driven beans are attached to queues at deployment time, so you won't be able to respond to queue creation events. Besides, queues are not meant to be created and destroyed in short cycles, they're rather designed to be long-living entities. If you need to deliver a message to one precise client, have the client listen on the server response queue with a message selector set to filter only the messages intended for this client (see javax.jms.Message API).
With topics it's exactly as you noted — each connected client will get a copy of the message — so again, it's not a good pattern to send to n clients a message that has to be discarded by n-1 clients.
MaDa;
You could stick one output queue (or topic) and simply tag the message with a header that identifies the intended client. Then, clients can listen on the queue/topic using a selector. Hopefully your JMS implementation has efficient server-side listener evaluation.

Resources