Rabbit MQ. 1 queue + Scale-out + SendLocal

I have a single application, started as a host + 3 slaves. All 4 instances is configured with the same endpoint. The host is posting commands that the slaves will execute.

        var endpointConfiguration = new EndpointConfiguration("myqueue");
        var transport = endpointConfiguration.UseTransport<RabbitMQTransport>();
        transport.ConnectionString("host=localhost;username=guest;password=guest");
        transport.UseDirectRoutingTopology();
        if (host)
            endpointConfiguration.SendOnly();

If I send the commands with SendLocal from the host, an Exception is thrown

System.InvalidOperationException: Cannot route to instances of this endpoint since it's configured to be in send-only mode.

I can see why this would be a helpful Exception, but in my case with the Scale-out on the same endpoint, I would like this to be valid. I know I could use Send with the name of the queue, which I want to avoid.

If this is not possible, I think the API is wrong when using RabbitMQ as transport. It should not be possible to set a endpoint name when using SendOnly. This is mandatory in the EndpointConfiguration constructor.

You configure the host to be “Send Only”, meaning that it only sends messages and is not able to process any incoming message. A SendOnly endpoint does not have a queue attached to it.

Doing SendLocal from the host is therefore impossible. SendLocal means “send this messsage to my own queue”, but as you indicated that the host is send only, that queue doesn’t exist. Hence the error…

Hi Marc, thanks for the response. I understand the error and why it in most cases would be correct. But with RabbitMQ and scale-out (hence there are readers on the queue) it could be nice to use SendLocal from a SendOnly, knowing the slave would take the messages.

Also, if this from a technically point isn’t possible, the API should not allow to configure SendOnly with an queue name (see EndpointConfiguration constructor). I know that MSMQ needs this, but with RabbitMQ this is very misleading.

Also, if this from a technically point isn’t possible, the API should not allow to configure SendOnly with an queue name (see EndpointConfiguration constructor). I know that MSMQ needs this, but with RabbitMQ this is very misleading.

An endpoint is not only the queue, we define it as “a thing that can send and receive messages” and even if you are not receiving messages identifying the endpoint that sent a given message is needed for things like auditing etc. This is why the name is mandatory. Does this make sense?

Can you share more details about your use case? (Why are your slaves different and not just multiple copies of a regular endpoint?)

Cheers,

Andreas

Yes makes sense, so maybe queue name and endpoint name should be 2 different things?

I am enabling NSB in an existing monolithic application (same old story). The application starts up in 2 different modes. 1 time as a host, and X times as slaves. The host gets input via web services. When called it sends NSB commands and then the slaves will handle the work. There is only one RabbitMQ queue, and the scale out works fine with X slaves. But I do not want the host to handle the commands it sends (therefor it is SendOnly)

I know I could do a Send with the queue name, but SendLocal would preferred.

Yes makes sense, so maybe queue name and endpoint name should be 2 different things?

They actually are 2 different things, we just default the queue name to a (depending on the transport) a sanitized version of the endpoint name.

You can control the queue name using:

But I do not want the host to handle the commands it sends (therefor it is SendOnly)

Yea, in that case, you would need to use an explicit send, I think the risk is low since you can just use a constant in code to make sure that you don’t get out of sync should the endpoint name change?

Have you considered splitting this up into two separate endpoints?

  • Api: Sendonly
  • Backend: Regular endpoint doing the processing

I can see some benefits around scaling out and also not having to take the API down when you make changes to the backend code?

Thanks for this explanation

Yes, I agree with that architecture. But in this legacy application, host and slaves are deployed, started and stopped together. There is only one binary.

In the end, this is what I will do (Send explicit)