ActiveMQ failover transport options not working as expected - activemq

I would like to use the ActiveMQ failover transport as described in https://activemq.apache.org/failover-transport-reference.html.
The default "retry forever" failover options work as expected.
However, since "forever" is sometimes too long, I tried to set some options in order to terminate the retry earlier.
For example, at startup I would like to terminate the application immediately if the connection to a broker can not be established at the first attempt.
I tried the simplest option:
failover:tcp://localhost:61616?startupMaxReconnectAttempts=0
but to my surprise, the retry goes on "forever" nevertheless.
I have tried many other combinations of options, like
failover:tcp://localhost:61616?startupMaxReconnectAttempts=0&maxReconnectDelay=10&maxReconnectAttempts=0&timeout=10
but without the desired result.
What am I doing wrong? How can I configure the failover transport such that it will terminate reconnection attempts at startup if a broker is not available?
I am using ActiveMQ version 5.15.9 (https://hub.docker.com/r/rmohr/activemq) and the Apache.NMS.ActiveMQ lib version 1.8.
The relevant code snippet is
var factory = new ConnectionFactory(connectionString);
var connection = factory.CreateConnection();
var session = connection.CreateSession(); // hangs here

There is Apache.NMS.ActiveMQ specific URI configuration: https://activemq.apache.org/components/nms/providers/activemq/uri-configuration which is not consistent with https://activemq.apache.org/failover-transport-reference.html, which brings a lot of confusion.
Following the NMS documentation I came up with a working solution:
failover:(tcp://localhost:61616)?transport.startupMaxReconnectAttempts=1
the composite URI must be in parentheses: failover:(tcp://localhost:61616)?... and not failover:tcp://localhost:61616?....
transport specific options must be prefixed with transport.
option transport.startupMaxReconnectAttempts=0 corresponds to infinite retries

Related

Symfony Messenger: retry delay not working with Redis transport

I have a Symfony 4 application using the Symfony Messenger component (version 4.3.2) to dispatch messages.
For asynchronous message handling some Redis transports are configured and they work fine. But then I decided that one of them should retry a few times when message handling fails. I configured a retry strategy and the transport actually started retrying on failure, but it seems to ignore the delay configuration (keys delay, multiplier, max_delay) and all the retry attempts are always made without any delay, all within one second or a similarly short timespan, which is really undesirable in this use case.
My Messenger configuration (config/packages/messenger.yaml) looks like this
framework:
messenger:
default_bus: messenger.bus.default
transports:
transport_without_retry:
dsn: '%env(REDIS_DSN)%/without_retry'
retry_strategy:
max_retries: 0
transport_with_retry:
dsn: '%env(REDIS_DSN)%/with_retry'
retry_strategy:
max_retries: 5
delay: 10000 # 10 seconds
multiplier: 3
max_delay: 3600000
routing:
'App\Message\RetryWorthMessage': transport_with_retry
I tried replacing Redis with Doctrine (as implementation of the retrying transport) and voila - the delays started to work as expected. I therefore suspect that the Redis transport imlementation doesn't support delayed retry. But I read the docs carefully, searched related Github issues, and still didn't find a definite answer.
So my question is: does Redis transport support delayed retry? If it does, how do I make it work?
It turned out that Redis transport supports delayed retry, but only since Messenger version 4.4.

NServiceBus 6.2 losing messages with RabbitMQ

I'm using NSB version6.2 and RabbitMQ version 4.
I'm using RabbitMQTransport. My RabbitMQ server is in a virtual machine in Azure. when I send messages, sometimes I'm losing messages without any error.
this is my NService Bus configuration.
EndpointConfiguration config = null;
string endpointName = ConfigurationManager.AppSettings.Get("NServiceBus.EndpointName");
config = configEndPoint.IsNullOrDefault() ? new EndpointConfiguration(endpointName) : configEndPoint;
int maximumConcurrencyLevel = ConfigurationManager.AppSettings.Get("NServiceBus.TransportConfig.MaximumConcurrencyLevel").ToInt();
config.LimitMessageProcessingConcurrencyTo(maximumConcurrencyLevel);
int numberOfRetries = ConfigurationManager.AppSettings.Get("NServiceBus.TransportConfig.NumberOfRetries").ToInt();
var recoverability = config.Recoverability();
recoverability.Immediate(
customizations: immediate =>
{
immediate.NumberOfRetries(numberOfRetries);
});
DefaultFactory defaultFactory = LogManager.Use<DefaultFactory>();
defaultFactory.Directory(this.DatabusDirectory);
defaultFactory.Level(LogLevel.Error);
config.IdealinkJsonSerializer();
config.UsePersistence<InMemoryPersistence>();
config.SendFailedMessagesTo("error");
config.AuditProcessedMessagesTo("audit");
// configure transport
config.UseTransport<RabbitMQTransport>().Transactions(TransportTransactionMode.ReceiveOnly);
var endpointInstance = Endpoint.Start(endpointConfiguration).GetAwaiter().GetResult();
Configuration of your endpoint looks fine with an exception of persistence.
Persistence is used for features that are not supported by the underlying transport natively. For RabbitMQ, there is not native mechanism to send delayed messages. Until version 4.3 persistence was used to store timeouts. If you use InMemoryPersistence, none of the information will be retained after endpoint restarts. Timeouts are needed for Recoverability feature, specifically delayed retries. From version 4.3 and above, persistence is not required for timeouts, but InMemoryPersistence should still not be used. You can chose other persistences based on technology and scenario at hand.
Please note that version 4.0.0 is not under supported versions. You should update to 4.3.x or 4.4.x and verify the behavior to see if you notice a message loss or not. In case you still losing messages, I suggest providing more details such as log file and handler code. If you can't share that publicly, submit a support case.
Hope that helps.

Error While running Mule

While Running the Mule, I am facing the below error:
Timeout waiting for mule context to be completely started
Please let me know the work around solution for this. The same integration is working fine i.e the query fetching is happening fine with other system having mule but the same is not working in my system. Please Suggest a way to overcome this.
Thanks in Advance...!
Goutham ...Did you configured timeout in your flow? If it is configured ..
1. is it configured in Munit which we need to look into run and wait scope..
2. Or is this coming during the shutdown of mule ?
You can set a timeout value to enable the current flow to complete. However, there is no built in method or utility to check what messages are in flight. You can connect a profiler and see the active threads (or just a thread dump), this should provide you an overview of what’s happening at the JVM level.
To ensure all inflight messages are processed you can shutdown mule in two steps:
Stop the flow(s) manually (this will prevent new messages from coming)
Stop Mule
Alternatively, you can set shutdownTimeout to a milliseconds value for a flow; hwoever this is not a global value.
https://docs.mulesoft.com/mule-user-guide/v/3.8/starting-and-stopping-mule-esb
http://grepcode.com/file/repo1.maven.org/maven2/org.mule/mule-core/3.7.0/org/mule/transport/AbstractMessageDispatcher.java
The second link will provide you the internal implementation of Mule's AbstractMessageDispatcher .Hope this helps.
Thanks

How to abort code when publish message on non exist queue in rabbitmq

I have wrote server-client application.
Server Side
server will initilise a queue queue1 with routing key key1 on direct exchange.
After initilise and declaration it consume data whenever someone write on it.
Client Side
client will publish some data on that exchange using routing key key1 .
Also i have set mandotory flag to true before i publish.
Problem
everything is fine when i start server first .but i got problem when i start client first and it publish data with routing key. When client published data there is no exception from broker.
Requirement
I want exception or error when i published data on non existing queue.
If you will publish messages with mandatory flag set to true, then that message will returned back in case it cannot be routed to any queue.
As to nonexistent exchanges, it is forbidden to publish messages to non-existent exchanges, so you'll have to get an error about that, something like NOT_FOUND - no exchange 'nonexistent_exchange' in vhost '/'.
You can declare exchanges an queues and bind them as you need on client side too. These operations are idempotent.
Note, that creating and binding exchanges and queues on every publish may have negative performance impact, so do that on client start, not every publish.
P.S.: if you use rabbitmq-c, then it is worth to cite basic_publish documentation
Note that at the AMQ protocol level basic.publish is an async method:
this means error conditions that occur on the broker (such as publishing to a non-existent exchange) will not be reflected in the return value of this function.
I spend a lot time to find do that. I have a example code in python using pika lib to show how to send messsage with delivery mode to prevent waiting response when send message to noneexist queue(broker will ignore meessage so that do not need receive response message)
import pika
# Open a connection to RabbitMQ on localhost using all default parameters
connection = pika.BlockingConnection()
# Open the channel
channel = connection.channel()
# Declare the queue
channel.queue_declare(queue="test", durable=True, exclusive=False, auto_delete=False)
# Enabled delivery confirmations
channel.confirm_delivery()
# Send a message
if channel.basic_publish(exchange='test',
routing_key='test',
body='Hello World!',
properties=pika.BasicProperties(content_type='text/plain',
delivery_mode=1),
mandatory=True):
print('Message was published')
else:
print('Message was returned')
Reference:
http://pika.readthedocs.org/en/latest/examples/blocking_publish_mandatory.html

How to be sure that channel.basic_publish has succeeded (internet connection error, ...)?

Im doing this :
channel.basicPublish("myexchange", "routing", MessageProperties.PERSISTENT_TEXT_PLAIN,
"message".getBytes());
I would like to retry later to send the message if the publish didn't succeeded (connection loss, ...) but basicPublish is a void function and there is no callback in the arguments
Any idea ?
You are looking an HA client,
By default you have to implement the feature by your self.
If you use java there is :
https://github.com/joshdevins/rabbitmq-ha-client (it's just a bit old but it think it still work).
Anyway, if you want implement the functionality you have catch the exception and re-try later.
If the client lose the connection you should re-connect the client before re-send the message.
On the version 3.3.0 the last features is implemented by default to the java client:
java client
enhancements
14587 support automatically reconnecting to server(s) if connection is
interrupted
This point is very important you want send the messages sequentially.
A simple solution is put the messages in a client list and then remove the message from the list only if the message has been sent correctly.
I think you could find interesting also the Publisher Acknowledgements