amazon-sqsnservicebus

NServicebus and multiple message types on same SQS Queue


I am fairly new to NServicebus and have run into a problem that I am thinking may have to do with my architecture.

I have one SQS queue with three SNS topics. So let's say:

Queue1
    MessageType1
    MessageType2
    MessageType3

I have created three NServicebus subscribers that will all run as three separate services. Each Subscriber is monitoring Queue1, and each one has a handler for a different message type. This is a rough sketch of how I am envisioning this to work:


                                         ---------MessageType3----------                  
                                        |                               |
                                        |     --MessageType2---------   |
                                        |   /                        |  |
                                        V  V                         |  |
[Outside Publisher] --MessageType1--> [Queue1] --MessageType1--> [Subscriber1]
                                        |  |
                                        |  |
                                       /    \
        [Subscriber3]<--MessageType3---      ---MessageType2--> [Subscriber2]

An outside service published MessageType1 to the Queue1. Subscriber1 picks up the message, does some processing, and publishes MessageType2 and MessageType3 back to the Queue1. Then Subscribers 2 & 3 pick up their respective messages and do their thing.

But what is happening is it is random which subscriber (1, 2, or 3) picks up the initial MessageType1. So then Sub2 picks it up, and errors because it doesn't have a handler for it.

Why is this happening? I thought the NServicebus would only pick up messages it has a handler for. Does NServicebus only like one message type per queue? Do I need to make separate queues for each message type?

I am hoping there is some way to configure the three subscriber services to only pick up the intended message, but I realize that maybe my understanding of NServicebus is lacking and I need to rethink my design.


Solution

  • Yep, you've got some misconceptions going on here, let's see if I can help clear them up.

    What you call "subscribers" are not subscribers. A queue defines a logical endpoint, and multiple processes monitoring that single queue are endpoint instances, not subscribers. They cooperate to scale-out on the processing of a single queue.

    A single queue can process multiple message types if you so choose, but when any endpoint instance asks for a message from the queue, it can't control which type it will get. The queue is just a line, it's going to get the message that's next, whatever that message is.

    So all the endpoint instances have to have ALL of the message handlers for messages that could go through that queue, or you will get that error.

    The only reason to have multiple endpoint instances is for scalability (process more messages at a time) or for availability (process messages on ServerA even if ServerB is getting rebooted.)

    Actual subscribers are different. Subscribers are where (in SQS/SNS parlance) a single SNS topic delivers copies of a message to multiple queues. You publish OrderPlaced and one copy goes to the Sales queue just so we can store that a sale was made, and a copy goes to the Billing queue (so that the credit card can be charged) and another copy yet goes to the Warehouse queue (so that they can start the process of getting it ready to put in a box.)

    The power of subscribers is that maybe 6 months down the line you create another Subscriber called CustomerCare that subscribes to OrderPlaced in order to store a running total of how much that customer has bought over the past year (see Death to the batch job) and the important bit is you DON'T have to go back to the original code where the order was placed—you just add another subscriber with its own queue.

    You might want to check out the NServiceBus step-by-step tutorial which goes over this in a lot of detail.