Scaling Azure IoT hub, partitioning and custom routes/endpoints - azure

Our solution use Azure IoT hub to connect thousands of devices to our backend. Devices report operating state, and based on this state we control the devices. The challenge is that devices are installed in groups, and state changes from a device, affect other devices in the group. Because of this we need to handle messages for a group in sequence. I would have preferred to use the devices groupId to partition messages. IoT hub and its default endpoint use deviceId to partition messages, and we've had to find other means of synchronising messages across partitions. Up until now, we've used a semaphore for this, which have worked fine as we're running everything in one process.
As we're nearing the point where a single App Service plan can no longer handle all messages, we need to scale the solution out. Thus, the semaphore will no longer suffice, and we need to find an alternative to distribute and synchronise messages.
The plan is to use custom routing in IoT hub, forwarding messages to one or more event hub endpoints. Currently I see two options:
If it's possible to affect partition key when using custom routes/endpoints, we could assign each device a groupId, and use that for partitioning messages. This would route all messages for a group to the same processor without any additional synchronisation, allowing us to simply scale out the event processor to handle more messages. Sadly, I've not found a way to affect the partition key of messages when using custom routes/endpoints either, and it does not look like this is a viable solution.
Add multiple custom event hub endpoints to IoT hub, and use groupId to route messages to endpoints. This will require us to deploy multiple event processor instances, each configured to consume messages for "its" event hub. Since event hubs have a minimum of 2 partitions, we would still need to use a semaphore to synchronise messages destined for the event processor. This seems like the only viable option, but adds quite a bit of complexity to scaling as we would have to manually deploy and configure each processor instance, instead of simply scaling out the App Service plan and using partitions to distribute messages.
Are there ways to change partition key when using custom routes/endpoint, allowing us to implement solution 1., or are there other better ways to achieve this?

The simple way to split an IoT Hub stream into the sub-streams based on the sources (groupId) is to use an Azure function (AF), see the following screen snippet.
The AF sample:
[FunctionName("FunctionSplitter")]
public static async Task PreProcessor(
[EventHubTrigger("%IoTHubName%", Connection = "connectionIoTHub", ConsumerGroup = "splitter")] EventData ed,
[EventHub("%EventHubName%", Connection = "connectionEventHub")] IAsyncCollector<EventData> outputEventHubMessages,
TraceWriter log)
{
log.Info($"IoT Hub trigger function processed an event {ed.SequenceNumber}");
// Create a clone
var edclone = ed.Clone();
edclone.PartitionKey = Convert.ToString(ed.Properties.ContainsKey("deviceGroupId") ? ed.Properties["deviceGroupId"] : "1234567890");
await outputEventHubMessages.AddAsync(edclone);
await outputEventHubMessages.FlushAsync();
}

Related

Azure Service Bus Topic Subscriber receiving messages not in order

I am using azure service bus topic and I have enable session for it's subscription.
With in the my logic app i am inserting data using sql transaction which are coming from topic
I am using topic Subscription(peek-lock) and
in subscriber level concurrency is set to default as follows
According to my Understanding, my logic app(subscriber) should read ALL the messages and have to processed in FIFO
my logic app is like
which means it should insert data to the table in ordered manner
however when i checked in the trigger log it shows correct order but in database level you can see the order is not happening
Message ordering is a delicate business. You can have either message ordering or concurrent processing, but not both. The moment you make message ordering a must, you lose the ability to have concurrent processing. This is correct for both, Azure Service Bus Sessions and Logic Apps concurrency control. You could process multiple sessions, but each session would be still restricted to a single processor. Here's a post about it.

EventGrid vs EventHub

I am working on a service fabric application and want to publish few events from this application and subscribe or process those publish events in another application.
I have tried EventGrid concept and observed that there is a delay while publishing and processing the events. So, now I am looking for other alternatives like EventHub or Queues, etc..
If anyone had already used EventGrid, EventHud or Queues, etc.. , Please do suggest which one will give more performance when we deal with more events.
Design Approach
We have migrated the tables from SQL service to Service Fabric. There is a view in SQL Service, and we are planning to implement that as a service in service fabric.
The implementation logic follows below.
Table 1 implemented service and we publish an event for each CRUD operation to EventGrid/ EventHud.
Table 2 implemented service and we publish an event for each CRUD operation to EventGrid/ EventHud.
We have created a view service where it listens to the events when any event sent to EventGrid/ EventHud, it will perform required calculations and store in the ViewService( It is a background job)
We are looking for a messaging service which gives more performance.
Have you seen this comparison and this one?
Anyway, can you clarify your requirements in terms of throughput and performance? It depends on a lot of factors including, but not limited to, the message size and the amount of messages.
Having used both Event Grid and Event Hub I'd say Event Hub works very well for many messages per second, say data streams from iot devices, but the performance of the downstream processing can be a bottleneck. You have to process them very fast in order to receive new events. Then there are partitions and consumer groups that can be of help to balance the load and have different processors for the same data but with different view of the data stream. (A fast processor for live displaying of sensor data and a slower one for storing the data for later analysis)
If you're talking about a few events generated by an application that triggers other apps to start doing some work based on those events Event Grid is a good fit. I haven't experienced much delay in receiving those events.
But bottom line, I think all services (Event Grid, Event Hub, Service Bus etc) support different use cases and that should be your first decision point.
Can you describe your publisher, subscriber, etc. and show your metrics of the Azure Event Grid usage?
You can use the portal screen snippets on the topic (publisher) and subscription (subscriber).
The following screen snippets are from my tester when manually have been fired few events.
Publisher side:
Subscriber side:
Metrics on the portal:
As you can see, the delivery destination processing time is ~1ms. The latency time on the publisher side (custom topic) is between 2-4ms.
Note, that the AEG is a PUSH->PUSH-ACK or PUSH->PULL-ACK eventing loosely decupled Pub/Sub model instead of the Event Hub model which is based on the PUSH->PULL mechanism, in other words, the Event Hub needs to host a listener and receiver for pulling an event from the partition.

How to route Event Hub messages to different Azure functions based on their message type

I have an Azure Event Hub over which I would like to send various types of messages. Each message should be handled by a separate Azure Function, based on their message type. What is the best way to accomplish this?
Actually, I could create some JSON container with a type and payload property and let one parent Azure Function dispatch all the messages payloads - based on their type - to other functions, but that feels a bit hacky.
This question basically asks the same - however it is answered how it can be done using the IoT Hub and message routing. In the Event Hub configuration I cannot find any setting to configure message routing though.
Or should I switch to an Azure Message Queue to get this functionality?
I would use Azure Streaming Analytics to route it to the different Azure Functions. ASAs allow you to specify Event Hubs as a source and several sinks (one of which can be multiple Azure Functions). You can read more about setting up Azure Streaming Analytics services through the Azure Portal here. You'll need to set up the Event Hub as your source (docs). You'll also need to set up your sink (docs). You write some MS SQL-like code to route the messages to the various sinks. However, ASAs are costly relative to other services since you're paying for a fixed amount of compute.
I put some pseudo code below. You'll have to swap it out based on how you configure you're ASA using the information from the attached MS Documentation.
SELECT
*
INTO
[YourOutputAlias]
FROM
[YourInputAlias]
HAVING
[CONDITION]
SELECT
*
INTO
[YourAlternateOutputAlias]
FROM
[YourInputAlias]
HAVING
[CONDITION]
Based on your additional info about the business requirements and assuming that the event size < 64KB (1MB in preview), the following screen snippet shows an example of your solution:
The concept of the above solution is based on the pushing a batch of the events to the Event Domain Endpoint of the AEG. The EventHub Trigger function has a responsibility for mapping each event message type in the batch to the domain topic before its publishing to the AEG.
Note, that using the Azure IoT Hub for ingestion of the events, the AEG can be directly integrated to the IoT Hub and each event message can be distributed in the loosely decoupled Pub/Sub manner. Besides that, for this business requirements can be used the B1 scale tier for IoT Hub ($10/month) comparing to the Basic Event Hubs ($11.16).
The IoT Hub has built-in a message routing mechanism (with some limitations), but a recently new feature of the IoT/AEG integration such as publishing a device telemetry message is giving a good support in the serverless architecture.
I ended up using Azure Durable Functions using the Fan Out/Fan In pattern.
In this approach, all events are handled by a single Orchestrator Function which in fact is a Durable Azure Function (F1). This deserializes incoming JSON to the correct DTO. Based on the content of the DTO, a corresponding activity function (F2) is invoked which processes it.

What is the best approach to copy messages from one service bus to another?

Let me give you a bit of background. I have an IoT app which is streaming data to a Service bus which has Topic filters with multiple subscribers on the LIVE environment, everything is good. Now I'm trying to create a test environment which is completely separate. As the data is streaming into LIVE I would ideally like a copy of all the messages arriving into this Test environment as well, so we can isolate the environments for the test team. So far the solutions proposed have been, is to add a second service bus connection in code and add the messages to both the buses the live one and the test one. This requires code change in many areas of the app and is clunky. I am looking for a more elegant approach where I can copy the messages arriving on a second bus. The first bus gets a copy and the second bus also gets a copy. Any advice would be appreciated?
Azure Service Bus does not support cross namespace forwarding as of today. If that would be possible, you'd be able to set up a subscription with auto-forwarding to another namespace. Until then, you will need to set up something custom indeed.
So far the solutions proposed have been, is to add a second service bus connection in code and add the messages to both the buses the live one and the test one. This requires code change in many areas of the app and is clunky.
In addition to that, it introduces the testing concern into your production application, which doesn't feel right. An approach I would try (note there are other options that could work as well) would be to have an additional subscription entity and introduce an Azure Function triggered by ServiceBusTrigger configured to the subscription entity you'll set up. The function would be able to leverage a ServiceBus output binding configured to use the testing namespace. The benefits of this approach are:
Your production application doesn't have to change.
You have complete control over what messages are pushed to the testing namespace vias filtering on the subscription.
You have control over flow of messages into the function by disabling/enabling the subscription or deleting it along with the function.
You will incur some additional cost for Function execution.
Pseudo code:
[FunctionName("CloneForTesting")]
[return: ServiceBus(TopicName = "topic", SubscriptionName = "subscription", Connection = "ProductionServiceBusConnection")]
public static string ServiceBusOutput([ServiceBusTrigger(QueueName = "queue", Connection = "TestingServiceBusConnection")]
Message message, ILogger log)
{
log.LogInformation($"Cloning message with ID {message.MessageId}");
return message.Clone();
}

Should I change how our microservices communicate?

Our application consist of 7 microservices that have some intercommunication. Currently we're using simple storage queues that a microservice publish events to (the number of events is relative low). Then we have a azurefunction for each queue that might call another microservices. This is working fine for us right now the services uses about 20 queues with a corresponding function.
Now we need to handle an blobstorage event, and I did some googling and a started to get really confused. Suddenly there was a lot of questions:
Should we switch to Azure Event Grid
It handles blobstorage without any limitations (functions blobstorage trigger has some)
It allows for multiple subscribers (storage queues does not)
It has a lot of fuz - maybe this is the new recommended way
I like the idea of one central thing, but it reminds me a bit about biztalk...
Should I switch to Azure Service Bus
It has a nice tool (ServiceBusExplorer) for monitoring the queues and listners, and I could to a repost of any failed events
It visulizes my azure functions subscribers nicely
Should I continue with only storage queues
A bit difficult to monitor, but it works nice
I'll be really thankful for any advice or insights to this question.
Thanks
EventGrid is great when you have notifications floating to multiple subscribers. Is that the case for you?
An example would be deferring messages. With queues you can defer a message, not with EventGrid. Whenever to choose Storage Queues or Service Bus depends on the specific requirement that you have. Do you need de-duplication? Or ordered delivery? If you do, Service Bus is the way. Otherwise Storage Queues is enough.
First of All, I would like to recommend these two articles, it will clarify most of your doubts about these services:
Choose between Azure services that deliver messages
Storage queues and Service Bus queues compared
Regarding Event Grid, it acts like a bridge between the publisher and the subscriber, where publisher will send messages and forget whether it has been processed or not, and the Event Grid will handle the retry if the receiver\subscriber does not acknowledge that it was processed successfully.
As you mentioned, storage queues has limitations, as such blob triggered functions, and maybe Service Bus, but it will depend on your design requirements. I would like to point out some things you might consider before moving to Event Grid.
Storage queues & Service Bus does not care about your message schema, in Event Grid you have to create a custom event based on their schema to wrap your event, so the publisher and subscriber has to understand Event Grid for that, not that is a big deal, but now you have both sides coupled to Event Grid.
If you want to send the event straight to your micro-service, you have to implement the subscription validation in your service, otherwise the service won't be able to receive the events
Event Grid only retry the delivery of your messages for 24 hours, if your service is down or not process the message correctly for longer than 24h, it will make the event dead. Currently, there is no way to query dead messages. Storage Queues and Service Bus are configurable how long you keep the message and it can be kept for many days.
Your service web-hook must acknowledge the receipt(http 200 or 202) of an event within 60 seconds, otherwise it will consider failed. If your operation is longer that that, you should send it to a queue and handle the locking from your service.
Probably there are more limitations, but these are the ones I remember right now that might change anytime soon, I think Event Grid is a great technology still on early days, and there is much to improve, I would recommencement only as a hub for Azure management events, I don't think it is ready for use as an application integrator.
Regarding your comment for queue manager, for Service Bus your have the Service Bus Explorer, and for Azure Storage you have the Azure Storage Explorer, where you can check the messages in the queue, is not the same as Service Bus, but helps.
It very much depends on how are you consuming the queue messages, you can take a look at this comparison: https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-azure-and-service-bus-queues-compared-contrasted
If you don't need ordering and if you don't have a strong limit on message volume, size or TTL, you can stick to storage queues.

Resources