Apache camel restarting the route - rabbitmq

I have a something as following:
from("rabbitmq://...")
.process(processor1)
:
.process(processorn)
.process(SendToExternalAppProcessor)
The SendToExternalAppProcessor.process() uses producer template to send the some request formed from the contents in the exchange parameter to another rabbitmq2 with sendBody() method.
The issue is that once SendToExternalAppProcessor.process() executes and above route executes, it restarts above route again along with the listener of the rabbitmq2.
What I am missing here? Is there any apache camel configuration that is slipping from my attention?
PS: I know I have not given any concrete code here so as to replicate the scenario on your machine, but am in hope that experienced head and eyes will be quick to recall and suggest something. (Also I cannot straightway share my project code and also its big and complex)
Update:
I tried by commenting sendBody() and still restarts the route. I must be missing something weird basic setting here...

I think this is just a misunderstanding of the way routes work. 'from' is not a one-shot event; it will keep accepting messages from the source until you explicitly tell the route to stop.

"from " works as a normal rabbitmq consumer. The route is designed as always running.
If you just want to transfer exchanges to another rabbitmq , "to" is enough.
from("rabbitmq://...")
.process(processor1)
:
.process(processorn)
.to("rabbitmq://rabbit2...")

Please let us know which version of Camel you are using.
Are you using transacted camel flow? If any transaction mode is on then one possible issue could be JMS commit acknowledgment. May be Camel is consuming message and processing but not acknowledging rabbitmq. So message is still there and consuming again and again by camel route. By default it is AUTO_ACKNOWLEDGE, so that should not be the case if not transacted camel route.

Related

One message processed OK, Next message rejected and goes to deadletter

I'm getting an strange behavior in my DEV environment. When I send a message to my queue it's dispatched correctly, but the next message (can be same content or different) always fails and is directly sent to my deadletter queue. And then this pattern is repeated, one OK, one sent to deadletter.
In my local setup, everything is working OK, but not in my DEV env so this makes a little difficult to debug/troubleshoot. Not sure what could be wrong or different. I'm new on RabbitMq so maybe I need to include more information (if so please let me know).
Does anyone have an idea of what could be causing it? Or does anyone have experienced something like this before?
RabbitMq Version is: 3.8.2
My rabbitmq.config file is:
[{rabbitmq_management,[{tcp_config,[{port,15672}]}]}, {rabbit,[{total_memory_available_override_value,3999997952}, {tcp_listeners,[5672]}, {loopback_users,[]}]}].
My two queues are configured this way:
**my-queue.dev**
Type: Classic
Features: D, DLX
**my-queue.dev.deadletter**
Type: Classic
Features: D
Kind regards!

What is Redelivery and Rollback in Apache Camel?

I am new to apache camel and couldn't understand the difference between Redelivery and Rollback.. Could you please help me understand this ?
Redelivery = something failed, but try again.
Rollback = something failed dont try again, but stop routing and fail.
Error handling can be a complex area to understand and master with Camel. My book Camel in Action 2nd ed has a full chapter on this subject.
There is also some docs online with some details (although not as elegant written and fully up to date - our website and docs on Apache Camel is currently undergoing a transition to a new modern look and feel): http://camel.apache.org/error-handling-in-camel.html

ActiveMQ DiscoveryAgent

I try to implement another DiscoveryAgent using a kind of database. I find this code and it helps me to understand how the DiscoveryAgent works :
https://github.com/sliard/multicastdb
But I don't know when the method registerService is called. When I changed the code of the multicast DiscoveryAgent to see when it's called, but it isn't when the DiscoveryAgent starts. But if it's not called, the broker can't advertize itself to the database...
Then I don't understand how a broker can communicate with another using the information of a DiscoveryAgent.
So if you can explain me when this method is called and if you have some documentation on the implementation of a DiscoveryAgent, it would be great.
Thanks in advance.
The registerService method is called from the Broker's TransportConnector when it is started which is at a different time from the start of the agent. You should take some time to look at the code of the various agents in ActiveMQ. The multicast version and the HTTP agent are good examples.
Keep in mind that the agents are written for both the Broker and the Client code to use so there is some code that isn't run from the Broker side and some that's not used on the client end. If you want to implement only a client side agent then you don't need to worry about the registration or advertisement bits, but if you want the broker to add itself to your DB implementation you would want to implement those bits so that the broker can add itself and do whatever your advertisement mechanism is.
The source code and test are your best documentation. Look at the code, run the tests and set breakpoints to see what's going on. You can even build from source and add in your own Logging if need be to get a better feel for it.

Publish and subscribe from same Queue in Rabbitmq

I am trying to set up broadcast messaging to all nodes in the system. When a new node joins the system, it publishes a message to everyone else to announce its entry. The way I have designed is that, a exchange exists to which all nodes will bind its own queue. Whenever a new node joins the system, it will bind its queue as well to the exchange and publish a message to the exchange. All nodes will receive this msg(including itself) and all other nodes(except this message) will send a "ack" message so that the new node will get to know the available nodes in the system. But somehow I couldn't able to get this working. My broadcast messages doesn't propagate to every node in the system. A simple one node publishing and rest consuming is working. But same node publishing and consuming is somehow screwed up somewhere.
Is there any other efficient way of doing this apart from the logic mentioned above? Or is there any restriction from rabbitmq perspective to achieve the above or is my code buggy and do I have to take a closer look at it.
The way you described it, your solution should work. However, without more detailed code examples (of the consume/publish logic in the "announcer" and the consume/acknowledge-publish logic in the other peers) it's difficult to debug.
A couple common problems could be tripping you up, though:
If you're considering "did I get responses back from all the other nodes" as the authority for "did the other nodes get my announce message?", you might need to acknowledge (basic.ack in AMQP) the messages your announcer is receiving as it gets them. Otherwise, it's possible you're not seeing subsequent messages due to consumer prefetch, though in most client libraries you'd have to be explicitly turning that on somewhere first.
Make sure your other peers (the ones receiving the "announce" and sending a message back) are acknowledging the message as well, or are consuming in "no-ack" mode. Otherwise, if they get blocked (via flow, rate-limiting, or prefetch), they will probably receive announces for awhile and then stop.
Make sure you're using a "fanout" type exchange. It sounds like you want unconditional-fanout behavior, so you don't need to muck about with topic routing. If you're using a topic or direct exchange, you may have a bug in your routing logic, in which case switching to fanout will work. I suspect you're already doing this though.
This is likely not the issue, but: you mention that your peers (not the announcer) are "acknowledging" the announce. Make sure that they acknowledge the announce by publishing a new message back to the announcer's queue directly (with no exchange, just a routing key), not by sending a basic.ack to RabbitMQ (that doesn't notify the sender of anything), and not by publishing an announce-received to the fanout exchange.
As an aside, I don't know why you're doing declare-queue/bind/publish as opposed to publish/declare-queue/bind; is there a good reason you need an announcing node to receive its own announce message? If you're after a "self-test" behavior, I think it's probably better to just implement a periodic "can things announce successfully?" health-check somewhere instead, though that's entirely subjective.
Have you tried the RPC style message, with a callback queue that you identify in the broadcast message's propeties? Like at the rabbitmq tutorial.

How to detect alarm-based blocking RabbitMQ producer?

I have a producer sending durable messages to a RabbitMQ exchange. If the RabbitMQ memory or disk exceeds the watermark threshold, RabbitMQ will block my producer. The documentation says that it stops reading from the socket, and also pauses heartbeats.
What I would like is a way to know in my producer code that I have been blocked. Currently, even with a heartbeat enabled, everything just pauses forever. I'd like to receive some sort of exception so that I know I've been blocked and I can warn the user and/or take some other action, but I can't find any way to do this. I am using both the Java and C# clients and would need this functionality in both. Any advice? Thanks.
Sorry to tell you but with RabbitMQ (at least with 2.8.6) this isn't possible :-(
had a similar problem, which centred around trying to establish a channel when the connection was blocked. The result was the same as what you're experiencing.
I did some investigation into the actual core of the RabbitMQ C# .Net Library and discovered the root cause of the problem is that it goes into an infinite blocking state.
You can see more details on the RabbitMQ mailing list here:
http://rabbitmq.1065348.n5.nabble.com/Net-Client-locks-trying-to-create-a-channel-on-a-blocked-connection-td21588.html
One suggestion (which we didn't implement) was to do the work inside of a thread and have some other component manage the timeout and kill the thread if it is exceeded. We just accepted the risk :-(
The Rabbitmq uses a blocking rpc call that listens for a reply indefinitely.
If you look the Java client api, what it does is:
AMQChannel.BlockingRpcContinuation k = new AMQChannel.SimpleBlockingRpcContinuation();
k.getReply(-1);
Now -1 passed in the argument blocks until a reply is received.
The good thing is you could pass in your timeout in order to make it return.
The bad thing is you will have to update the client jars.
If you are OK with doing that, you could pass in a timeout wherever a blocking call like above is made.
The code would look something like:
try {
return k.getReply(200);
} catch (TimeoutException e) {
throw new MyCustomRuntimeorTimeoutException("RabbitTimeout ex",e);
}
And in your code you could handle this exception and perform your logic in this event.
Some related classes that might require this fix would be:
com.rabbitmq.client.impl.AMQChannel
com.rabbitmq.client.impl.ChannelN
com.rabbitmq.client.impl.AMQConnection
FYI: I have tried this and it works.