Good Day.
Is there a way to retrieve routing keys for an existing exchange (fanout or topic) via the browser based UI?
I don't have access to the client source code (producer) to see which routing keys are being sent to the model.
Thank you.
Edit:
The idea is to try and latch on to an existing fanout exchange (which I cannot reconfigure). I want to create a new exchange, bind it to this one and only filter out certain messages.
Use the HTTP API:
http://localhost:15672/api/exchanges/vhost/name/bindings/source
A list of all bindings in which a given exchange is the source.
for example:
http://localhost:15672/api/exchanges/%2F/my_exchange/bindings/source
[
{
"source":"my_exchange",
"vhost":"/",
"destination":"my_queue",
"destination_type":"queue",
"routing_key":"my_routkey",
"arguments":{
},
"properties_key":"my_routkey"
}
]
Related
Here comes my code on my publisher app (a netcore API).
services.AddMassTransit(masstransit =>
{
masstransit.UsingRabbitMq((context, cfg) =>
{
cfg.Host(new Uri("rabbitmq://srv-docker-dev-01"), "/", h =>
{
h.Username("guest");
h.Password("guest");
});
cfg.ReceiveEndpoint("implantacao", e =>
{
e.ConfigureConsumeTopology = false;
e.Bind<ClienteAlteradoEvento>();
});
});
});
Even before I create a consumer, my RabbitMQ shows a skipped queue.
And the message is delivered on this __skipped.
Can someone tell me what I'm doing wrong?
Just a few points:
My consumer will not have access to the event class of my producer.
I will have 2 queues which have to consume my API. I'll probably configure another receive endpoint.
I thought I should have only 1 exchange for each microservice. Like, all the events published by comercial microservice, should use the same exchange, but MassTransit is creating one exchange each type. Is that correct?
Any thoughs and ideas, will be welcome. I'm just learning about RabbitMQ.
EDIT
Microservice A: Have endpoints to receive user input data of customers. Users send data like names, contracts, and anything else (many different types of data can be changed on different endpoints). Every time a customer is updated, this API should publish messages to update other microservices too. Lets say we have at least 3 different events: CustomerDataUpdatedEvent, CustomerAddressUpdatedEvent, CustomerContractsUpdatedEvent.
Microservice B: Want to consume the updates from costumer published by Microservice A. We don't have access to CustomerDataUpdatedEvent, CustomerAddressUpdatedEvent, CustomerContractsUpdatedEvent classes. We should build our class type on its side.
Microservice C: Want to consume the updates from costumer published by Microservice A. We don't have access to CustomerDataUpdatedEvent, CustomerAddressUpdatedEvent, CustomerContractsUpdatedEvent classes. We should build our class type on its side.
Neither B or C have access to class type on microservice A.
Is that possible? Does it makes sense?
Thanks
You are configuring a receive endpoint without any consumers on it. So any message produced that arrives on the queue will just be copied to the _skipped queue.
I'd suggest reading some documentation to get the feel for how messages, consumers, and endpoints are configured.
I wouldn't suggest using a single exchange (or even a single queue) for all the messages in a service, but since you're just learning I don't really know what else to suggest without details.
It is not recommended by Chris Patterson here, you could use RabbitMQ.Client. but it is not impossible.
In this documentation there are two ways to better understand:
Using ISendEndpoint Send<T>(...)
var endpoint = await busControl.GetSendEndpoint(new Uri("exchange:my-exchange"));
await endpoint.Send(new {});
Using IBus Publish<T>(...)
var bus = Bus.Factory.CreateUsingRabbitMq((cfgBus) =>
{
cfgBus.Host(host: eventbusoptions.Host);
// Remove default wrapper message
cfgBus.ClearSerialization();
cfgBus.UseRawJsonSerializer();
// Set exchange name
cfgBus.Message<SubmitOrder>(top =>
{
top.SetEntityName(eventbusoptions.ExchangeName);
});
// Configurations per Publish
cfgBus.Publish<SubmitOrder>(top =>
{
top.ExchangeType = eventbusoptions.ExchangeType;
top.Durable = false;
top.BindQueue(eventbusoptions.ExchangeName, eventbusoptions.QueueName, bind =>
{
bind.RoutingKey = eventbusoptions.RoutingKey;
bind.ExchangeType = eventbusoptions.ExchangeType;
bind.Durable = false;
});
});
});
await _bus.Publish<SubmitOrder>(order, context => context.SetRoutingKey(_eventBusOptions.RoutingKey));
I just realize MassTransit isn't what I'm looking for right now.
I read about RabbitMQ and people told me MassTransit should be a nice approach but I disagree. Maybe for some scenarios it would be perfect, but when you can't have the same type on both projects, it's a pain.
The "exchanges must be type" isn't flexible enough.
The problem of my question is the answer gave by Chris. But Mass will not do what I want. His answer is right, btw.
I'm attempting to update the "Springwolf" library (used to document async API definitions) to support rabbit consumer listeners using spring cloud functions for spring cloud stream. In order to accomplish this I need to find from application context
spring cloud functions defined.
map this to a channel name
map that channel name to its binding.. hopefully pulling out exchange, queue and routing key values.
I've been able to successfully track down the defined functions, get the expected payload type of the function, and map that to a channel name using defined values in application.properties.
Depending on our application properties are set up I can get the other info from there but this is not always possible. Is there a way I can pull this data from defined spring beans.
I've found bean "bindingService" has a private field "consumerBindings" which has a field "destination" which has a field "bindings" and those bindings have all of the details that I need... but given they're private and buried I don't think this would be a good way to go.
I've also found spring.cloud.stream-org.springframework.cloud.stream.config.BindingServiceProperties has a "getBindings" method on it, but those values appear to be incomplete. for instance with a rabbit consumer defined as below the "group name" is generated randomly but its name is not available from the Bindings provided in BindingServiceProperties
spring.cloud.stream.bindings.anotherConsumerMethod-in-0.destination=someDestination2
spring.cloud.stream.bindings.anotherConsumerMethod-in-0.consumer.bindingRoutingKey=testgroup.testDestination.queue2
Any help/guidance would be awesome... also if the answer is "you can't do this" I completely understand.
I made spring batch application that produces amqp (rabbitmq) messages which consists of list of json objects. Messages have headers with some metadata. Spring cloud stream app is consuming messages, and I used functional approach. How can I access the headers?
Is it bad approach to use message headers for anything but routing?
If your function signature in Spring Cloud Stream application accepts Message (for example):
#Bean
public Consumer<Message<?>> consume() {
return message -> {
message.getHeaders()....
};
}
. . then you can simply access message headers.
We're also working on simplifying it a bit.
No, it s not a bad approach to use message headers for anything but routing.
Think of Message Headers as meta information, only relevant to the current message . . . anything that is important for the current message but not after.
I have an fanout exchange (named : test_exchange) for which I allow users to dynamically create queues. In order to prevent them to create whatever they want I have restricted their access this way:
Configure : test_exchange.*
Write : test_exchange.*
Read : test_exchange.*
When creating a queue to bind to the exchange, they have to use the following naming convention : test_exchange.(some guid), for example : test_exchange.hjLgS6JRTzbuQ48FyWFIZQ
This works fine. Except that they can also create exchanges if they respect the naming convention.
According to RabbitMQ documentation
QueueDeclare : needs the configure rights
QueueBind : needs the write rights
The problem is that to create an exchange you need the same configure rights.
What could be the solution to allow a consumer to only create a queue, and bind it to a specific exchange ?
And no other access rights?
I am still confused when it is appropriate to use the Message type in WCF like below
[ServiceContract]
public interface IMyService
{
[OperationContract]
Message GetData();
[OperationContract]
void PutData(Message m);
}
Why would you want to use it?
Can you use it for streaming?
Thanks
MSDN lists the follow reasons for using the message class directly:
When you need an alternative way of creating outgoing message contents (for example, creating a message directly from a file on disk) instead of serializing .NET Framework objects.
When you need an alternative way of using incoming message contents (for example, when you want to apply an XSLT transformation to the raw XML contents) instead of deserializing into .NET Framework objects.
When you need to deal with messages in a general way regardless of message contents (for example, when routing or forwarding messages when building a router, load-balancer, or a publish-subscribe system).
See Using the Message Class for more detailed information.
Edit to address the streaming question
I didn't find a definitive answer in my quick scan via google, but the article above states "All communication between clients and services ultimately results in Message instances being sent and received" - so I would assume it could be used directly in streaming.
While the reasons listed by Tim are valid, we use messages directly in our services to create one uber routing service.
we have one service that can take any method call you throw at it, Clients are generated by wsdls supplied from multiple sources.
This service would take the message, examine its content and route it accordingly.
So in my opinion if you want to get closer to the wire, or when you dont know the type of incoming messages, you can use the message in the signature directly.
Streaming is a separate concept than message signature, streaming is supported by wcf under very specific bindings and security mechanism and the method signature has to be very specific (i.e it should return/accept stream). Also in streaming the actual stream of data travels outside the scope of soap message.