0

I working on a system in which I need to manage ordered messages throw a service bus. In my company we have everything on Azure cloud and I'm using Azure service bus for messaging. I read about the session and it seems that it could solve my challenge out of the box with Azure service bus but it is working only with a single instance. Once I scale out the we job to multiple instances, more than one instance is consuming the same messages from the same session. In my POC I using a Topic with a subscription.

Is someone able to make it work with scaling to multiple instances of the receiver? The second option I have is to implement by myself the Resequencer enterprise pattern, do you have any suggestions?

Here is the code I'm using to receive the messages:

static async Task InitializeReceiver(string connectionString, string queueName, CancellationToken ct)
    {
        var receiverFactory = MessagingFactory.CreateFromConnectionString(connectionString);

        ct.Register(() => receiverFactory.Close());

        var client = receiverFactory.CreateSubscriptionClient(queueName, "parallel", ReceiveMode.ReceiveAndDelete);

        client.RegisterSessionHandler(
            typeof(SessionHandler),
            new SessionHandlerOptions
            {
                AutoRenewTimeout = TimeSpan.FromMinutes(5),
                MessageWaitTimeout = TimeSpan.FromSeconds(120),
                MaxConcurrentSessions = 100,
                AutoComplete = false
            });
    }

Here is the code I use for processing:

public async Task OnMessageAsync(MessageSession session, BrokeredMessage message)
    {
      await ProcessMessage(session, message, currentInstanceId, recipeStep);
      // If I process the last message of the session
      if (message.Sequence == numberOfMsgPerSession)
        {
            // end of the session!
            await session.CloseAsync();
            logger.LogInformation($"Session with id {message.SessionId} is completed.");

        }

}

Thanks. Regards.

OaicStef
  • 167
  • 2
  • 8

2 Answers2

1

I used timer to trigger my methods in Web jobs. When it comes to scaling, the number of timers got increased proportional to the number of instances. There, I replaced the timers with Azure Service Bus Topic Subscriptions. As the messages can be received only once, the methods got triggered only once even there are more than one running instances.

I had an active receiver listening for the messages, check here for creating a active listener.

As you were saying that the messages are received in multiple instances, you may have peeked the messages, instead of receiving it. Peeking the message do not delete it form the Subscription. Receiving it only will delete it from the Subscription, resulting in making the message not available for other receivers.

Arunprabhu
  • 1,454
  • 9
  • 15
  • Hi, the issue I have is happening using Session, did you use them, too? – OaicStef Jul 24 '18 at 11:27
  • Nope, I used Topic with multiple Subscriptions with Rules. – Arunprabhu Jul 24 '18 at 11:29
  • Without Sessions I won´t be able to solve the ordering for the messages processing. – OaicStef Jul 24 '18 at 11:30
  • Even when using Sessions, the messages can be received only once. Are you sure that you used ReceiveAndDelete mode for client and AcceptMessageSession() before receiving. – Arunprabhu Jul 24 '18 at 11:38
  • Actually I used the PeekAndLock and this other method for "Active receiver" RegisterSessionHandler. I´ll try to change the code using ReceiveAndDelete and AcceptMessageSession. I hope to solve the problem. thank u. I´ll let you know. – OaicStef Jul 24 '18 at 11:40
  • If you change Peek lock to Receive and delete, it will solve your problem for sure :-) – Arunprabhu Jul 24 '18 at 11:45
  • Hi again, it didn't solve the problem, suddly when I make the test with few messages it goes fine, but when I send 200 messages per session, with 10 sessions, it duplicates processing. I think that I'll implement by myself the Resequencer Enterprise Service bus Pattern. – OaicStef Jul 24 '18 at 13:05
  • Messages can be received only once. I am not sure why there is duplication in processing the messages. Is there a possibility that duplicate messages are sent to the Subscription? – Arunprabhu Jul 24 '18 at 13:27
  • No, that is not happening, because I´m tracking all the events sent, processed into a sql server db, so I see the duplication in processing. It is really strange and I see that It is happening when I scale out on Azure but in local it seems to work fine. – OaicStef Jul 24 '18 at 13:29
  • Can you share the message processing logic you used in you end – Arunprabhu Jul 24 '18 at 13:35
  • Hi, I posted the code I use on the receiver side as you suggested. I want to repeat that it is working in local with multiple instances but it is failing on Azure, maybe it is due some bug on Azure side? – OaicStef Jul 25 '18 at 11:32
0

I solved it. If you see the code I posted in the question, for each session I close it when I'm processing the last message based on its sequence number. Once, I removed that piece of code, everything started working properly, I send 200 messages per session with 10 sessions. The messages are processed ordered for each session, and no more than one instance take a session as I was expecting.

Thank you all. OaicStef

OaicStef
  • 167
  • 2
  • 8