stomp.js creating rabbitMQ queue without routing key - rabbitmq

I am using RabbitMQ for pub-sub. I have an exchange of type topic, I am subscribing to the exchange using stomp.js
var ws = new SockJS('http://127.0.0.1:15674/stomp')
var client = Stomp.over(ws)
client.subscribe('/exchange/foo', function() {...})
But the problem with a subscription is for every new host, a separate queue is created with a name with a prefix stomp-subscription- and an empty routing key. I want to set the routing key as #.
Please advise if something is wrong with the above approach.

The RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.
I suggest reading this document as it looks as though you're not using the correct URL. The docs say the path is /ws, not /stomp.
To subscribe to a routing key, you must change your code to /exchange/foo/PATTERN where PATTERN is the pattern matching the routing key. This is documented in the STOMP plugin docs.

Related

MassTransit exchange to exchange bindings benefit

The document said
Published messages are routed to a receive endpoint queue by message type, using exchanges and exchange bindings. A service's receive endpoints do not affect other services or their receive endpoints, as long as they do not share the same queue.
As I know, create one ReceiveEndpoint like below will then create one exchange and one queue with the same name (e.g. some-queue), and will bind this exchange to the message type's exchange.
services.AddMassTransit(x =>
{
x.AddConsumer<EventConsumer>();
x.UsingRabbitMq((ctx, cfg) =>
{
cfg.ReceiveEndpoint("some-queue", e =>
{
e.ConfigureConsumer<EventConsumer>(ctx);
});
});
});
However, I don't get the point why bother have additional "some-queue" exchange. Any example usecase will be helpful.
I cover the reasons for the topology in several videos, including this one.
I was looking for the answer to this question myself. For the benefit of the answer I paste some revised quotes of the linked video from Chris here:
MassTransit has done this since the very first versions.
If you would want to to send directly to a queue you would have to either:
Specify a blank exchange name and set the routing key equal to the queue name.
or
Send to an exchange that's bound to the queue.
You can't send to a queue directly.
[...]
When we looked at the topology for the broker for MassTransit, the approach we took is to create an exchange with the same name as the queue. This gives us some actually really cool features:
Let's say I want to keep a copy of every message sent to my endpoint. I can do that by just creating another queue and binding it to that exchange. That lets me do like a wiretap which is actually a messaging pattern.
[...]
When you're troubleshooting and ask yourself: "Why didn't the service do what I suspected?": With this I can go at that queue and then I could go
to my wiretap queue and look at every message that was received. This is a really cool way to kind of steal traffic and look at it and figure out what's going on.

NestJS integration with rabbitmq- specify exchange name

I am integrating a NestJS application with RabbitMQ and i followed this tutorial
From the tutorial i can see that message consumer can connect to the rabbitMQ broker using a queue name, but actually i want to create a temporary queue that connects to an exchange. I cannot find an option to specify the exchange name in the queue options specified in the tutorial. can someone please point to the right configuration to use to specify an exchange instead of queue?
is it possible to specify an exchange name inside the 'queueOptions' structure?
From what I understand from your tutorial (I don't know NestJS), createMicroservice only connects to a queue (or create it if needed). In other words, it performs assertQueue operation:
var queue = 'task_queue';
channel.assertQueue(queue, {
durable: false
});
If you want to bind a queue to an existing exchange, you need to perform bindQueue operation:
channel.bindQueue(queue, exchange, '');
Thus you can't bind to an exchange using queueOptions. Take a look at the official Rabbitmq documentation, especially the "Temporary queues" and following "Bindings" sections.

rabbitmq: how to setup routing keys per queue (and message) so that it can get messages for that queue and message destined for all queues in a topic?

I am very new to messaging and rabbitmq and trying to setup bindings in rabbitmq control panel to support the following scenario (pardon the pseudo):
queue named one
queue named two
I would like to send message destined:
only for one
only for two
for both one and two
Currently rabbitmq setup looks like this:
to: one; routing: one;
to: two; routing: two
When I publish a message I use this kind of setup:
routing key: one -> message is delivered to one;
routing key: two -> message is delivered to two;
With what routing key value do I publish a message so that both queues receive it? Or how do I setup my bindings.
You can set up wild card characters for your routing keys.
You could do routing_key: 'all', routing_key: 'all.one'or routing_key: 'all.two'
Obviously the example is contrived and you would choose more meaningful routing key names like "logging.telegraf" or "logging.events"or "weather.houston" etc. Basically you can set up something of a hierarchy using dotted notation.
Hope that helps.
Check out the official docs on topics and the use of * or #
http://www.rabbitmq.com/tutorials/tutorial-five-ruby.html

Change default exchangeType as fanout through Spring cloud stream or rabbitmq server config

I have two microservices Student and Teacher
in Student microservice I have created MessageSink for exchange XYZ
#Input("XYZ")
SubscribableChannel xyz();
and in Teacher microservice I have configured exchange XYZ as a fanout
application.properties
spring.cloud.stream.rabbit.bindings.XYZ.producer.exchangeType=fanout
spring.cloud.stream.bindings.XYZ.contentType=application/json
But problem I am facing here is Student service is starting before Teacher service and it is creating XYZ exchange with type Topic.
To tackle this I have added exchangeType in both the services (i.e consumer as well as producer). As services are growing in numbers, these configurations are growing in numbers.
I want to change the default exchangeType as fanout, so following are few questions.
is there any way to change default exchangeType as fanout instead of topic in spring-cloud-stream?
Is there any way to change default exchangeType through rabbit-mq configuration?
As a work around I planning to keep exchangeType as topic and routing key #. But the problem with this approach is stomp client is creating queue for every browser host with queue name as stomp-subscription-randomString and blank routing key. So is there any way to provide routing key while subscribing to stream? I am using /exchange/exchangeName as exchange URL
There is some documentation on the matter: https://docs.spring.io/spring-cloud-stream/docs/Elmhurst.RELEASE/reference/htmlsingle/#_configuration_options_4
You may consider to play with this option:
exchangeType
The exchange type: direct, fanout or topic for non-partitioned destinations and direct or topic for partitioned destinations.
Default: topic.
Therefore it will look in our config like:
spring.cloud.stream.rabbit.bindings.XYZ.consumer.exchangeType=fanout
There are some other options, like: declareExchange=false and bindingRoutingKey to consider as well.

Send a message to every AMQP client, except me

I use RabbitMQ as following :
Create a direct exchange "FooExchange"
Connect a client "A" to "FooExchange" with a queue named "client_A_queue"
Connect a client "B" to "FooExchange" with a queue named "client_B_queue"
Connect a client "C" to "FooExchange" with a queue named "client_C_queue"
Now, when client "A" publish a message to the exchange, everyone receive it.
Is there anyway to avoid client "A" to receive its own messages ?
(and the same for every client : a client should not receive its own messages)
For the moment I have added a "sender" header with a sender UniqueID and I filter these messages in the client source code, but I think that a better solution should exist.
(in real world situation, I can have many clients, not all clients knows the existence of all other clients)
Thanks.
EDIT :
Maybe direct exchange is not the good solution. Is there any way to fit my needs only with exchange/queue/routing configuration or should I use code in client applications to filter these messages ?
Of course, if I have 1000 clients connected, I can't really use one routing key for each client and send message to 999 routing keys jsut to exclude one.
The short answer is that this can't be done in RabbitMQ, directly.
There are no negations in routing key matches, so you can't say "all, but not this one" with routing keys or bindings.
For the moment I have added a "sender" header with a sender UniqueID and I filter these messages in the client source code, but I think that a better solution should exist.
this is pretty much what you need to do
From your comment
Every client publish messages the same way : to "FooExchange"
exchange, with routing key "FooKey". Every client bind it's queue to
"FooKey" on "FooExchange
You are not doing the publishing in the correct way. You must define to which exchange and which routing key.So each subscriber with different routing key, since this is what you want. Check the first tutorial on rabbitmq website. Also bare in mind that when using direct exchange, the name of the queue on the subscribing side is the same as the routing key on the publishing side.
Here is how direct exchange works
taken from here.
EDIT to answer the edit in the question
I didn't really understand this part
I can't really use one routing key for each client and send message to
999 routing keys jsut to exclude one.
You would need to specify more precisely what you need.
Anyhow, I suggest that you check out all the types of exchanges:direct, fanout, topic and headers. More info is already in the link I have provided, under the picture.
EDIT2:
I think I finally understood what is the use case.
If there is no other criteria which you could use to mark the messages or clients, then you'd have to use fanout exchange, and simply don't react on the message if it's "self-sent". Potentially you could use the headers exchange and use some kind of mappings, but it seems that it would end up on the same. AFAIK, there is not pattern for topic exchange that would include NOT something.