Home > Enterprise >  Skip SQS messages while consuming a queue
Skip SQS messages while consuming a queue

Time:11-19

I have a message producer, sending messages like {"user_id": 1, "message": "Ciao"} to a SQS queue.

I have three instances of a Websocket API, their names being A, B and C.

Let's say five users connect to that API, their IDs being 1, 2, 3, 4 and 5.

Each user connects to the API and my balancer (sticky ofc) makes the clients connect to the API this way:

A: 1, 3
B: 5
C: 2, 4

Now, the Websocket API is the consumer of the SQS queue mentioned above.

When I enqueue a message for user 1, any consumer could dequeue it first, let's say C does.

Instance C can't do anything with messages for user_id 1. A does hold the actual connection to that user.

In my mind, this would work like: any message will be received by all of the three API instances.

  • C will read it, and leave it in the queue
  • B will read it, and leave it in the queue
  • A will read it, process it and remove it from the queue

My question is:

Is the above workflow feasible to implement with SQS?

Is it possible to read a message from the queue and leave it there? Or do I have to dequeue it and re-enqueue it if not processable by the current consumer?

CodePudding user response:

With only SQS it is feasible (but require customised code in the consumer).

Example: SQS delete message based on the Acknowledgement sent from a consumer. If a consumer sends an acknowledgement, SQS will delete the entry. So, one way to design is:

a) Consume message b) Check if it is the desired message c) If it is, then send an ACK to SQS and SQS will delete the entry d) If the message is not the desired message, do not send and ack and SQS will keep the record

Other approach:

you can combine SQS with SNS to achieve it.

You can have 3 separate queues for 3 Websocket API e.g. SQS_A, SQS_B, SQS_C. And you can have one SNS topic say, MyTopic. Then, you can make the Queues subscribed to the SNS topic based on subscription filtering.

Example,

  1. SQS_A will be subscribed to the SNS topic if the event filter has user_id 1 and 3 in it.
  2. SQS_B will be subscribed to the SNS topic if the event filter has user_id 5 in it.
  3. SQS_C will be subscribed to the SNS topic if the event filter has user_id 2 in it.

The event filtering looks like this for SQS_A:

{
  "EventType": [
    1,
    3"
  ]
}

So... now when the publisher is publishing the message, it will publish the message to the SNS topic along with the event type.

Example:

sns.PublishInput{
        Message:  msg,
        TopicArn: topic,
        MessageAttributes: {
            EventType: {
                DataType: "String",
                StringValue: <listOfUserId>
            }
        }
}

Now, the SNS will only send this message to the SQS_A and not the rest of the SQS. So, only Websocket A will consume the message.

More: enter image description here

In your use case,
[Mesage for user 1/3] -> SNS -> SQS for A -> Websocket A only gets messages for user 1/3
[Mesage for user 5] -> SNS -> SQS for B -> Websocket A only gets messages for user 5

Please note that SNS topic in both cases remains the same. But the subscriber filters the message and you'll have multiple SQS queues.

  • Related