How to send a message to only one Azure Service Bus Subscription? - azure

I have the following scenario: I have 2 microservices subscribes in an Azure Service Bus, one microservice to send push notifications and another to send emails, these microservice will never work together, so the message will execute only by one microservice.
I was searching and looks like a good idea to send the message to a Topic and have a filter to choose what microservice should execute the operation.
So I have two questions:
Should I use Topics and filters? Not sure if's the better practices.
If yes, exist a way to send the message to the correct subscription? For example, I publish a message to subscription X instead of publishing for all subscriptions.
Thanks

Should I use Topics and filters? Not sure if's the better practices.
Yes. This is a classic use case to topics and subscriptions.
If yes, exist a way to send the message to the correct subscription? For example, I publish a message to subscription X instead of publishing for all subscriptions.
The way publishing works is that you publish it to the topic, the topic takes the messages and validates against the filters on all the subscriptions. Subscriptions with the satisfying filter criteria receive the message. Subscriptions that do not have filter criteria satisfied are skipped. There are three types of filters, Boolean, SQL and Correlation. Boolean filters are less relevant to you. Correlation or SQL filters will do the job. You can find more info on filters in my post.
What I would suggest here is to "stamp" each message with the method of notification. Since you're going to use a single notification method per method, the Correlation filter would be the simplest and most efficient. Notification method value could be assigned to the Label system property of the outgoing messages and a correlation filter on both subscriptions (one for email service and one for push notification services). For example (pseudo code):
var message = new Message();
// custom logic to determine what notification method to use
if (notificationMethod == NotificationMethod.Email)
{
message.Label = "email";
}
else
{
message.Label = "push";
}
// publish the message to the topic
And the two filters setup would be:
// email notification service subscription
var emailFilter = new CorrelationFilter();
filter.Label = "email";
// push notifications service subscription
var pushFilter = new new CorrelationFilter();
filter.Label = "push";
Creating subscription with a given filter (email for example):
var management = new ManagementClient(...);
await management.CreateSubscriptionAsync(new SubscriptionDescription("topic", "subscription"));
var client = new SubscriptionClient("topic", "subscription");
await client.AddRuleAsync(new RuleDescription(
{
Filter = emailFilter,
Name = "email filter"
}));

Related

The Azure Alerts using webhook to Slack is not working

I'm using Azure Alerts to use webhooks. I added the webhook in the action group. The URL I used is the one from Slack.
I also added a Notification Type Email. The notification email gets triggered but I am not receiving any message in the Slack channel.
I was able to push messages to the webhooks using postman hence I know my webhook is correct. But Azure Alert is not able to trigger the webhook. I am not receiving any messages in the Slack channel.
Azure Monitor sends a notification with its own schema definition. Slack doesn't recognize it, so you cannot see any notifications in the channel. It is possible to create a Logic App or Azure Function to transform the default schema.
Here the more information about it:
https://learn.microsoft.com/en-us/azure/azure-monitor/alerts/alerts-common-schema
Slack expect a json object when using webhooks. When sending directly from azure alert you will get bad request.
Every slack channel has an e-mail adress. You can post messages to the channel using that email in azure alerts
Anyone looking for using Slack and Azure Alerts. This seems to work fine:
...
webhook_receiver {
name = "Slack"
service_uri = "https://hooks.slack.com/services/secret"
use_common_alert_schema = false
}
Then in the scheduled query rules alert:
...
action {
action_group = [data.azurerm_monitor_action_group.actiongroup.id]
email_subject = "Disk storage at less than 10%"
custom_webhook_payload = "{ \"text\" : \"Warning: Storage has less than 10% diskspace remaining!\"}"
}

Azure Service Bus - Multiple subscribers don't receive all messages

I'm using the code to implement Azure service bus topics that can be found here:
https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-dotnet-how-to-use-topics-subscriptions
I've tried to run two instances of the subscriber program, which holds these methods:
private static void RegisterOnMessageHandlerAndReceiveMessages()
{
var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
{
MaxConcurrentCalls = 1,
AutoComplete = false
};
_subscriptionClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
}
private static async Task ProcessMessagesAsync(Message message, CancellationToken token)
{
Console.WriteLine($"Received #{message.SystemProperties.SequenceNumber} message: {Encoding.UTF8.GetString(message.Body)}");
await _subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);
}
However, this doesn't allow both subscribers to recieve the message, it is recieved one message each split across both subscribers.
How does I ensure both subscribers get all the messages coming from the bus?
Azure Service Bus is a broker with Competing Consumer pattern when it comes to retrieving messages. This is expected behaviour. What you have here is a scaled-out processing endpoint, where both are trying to process messages from the same subscription. The messages are distributed between these two competing consumers. If you need to distribute the same message to more than a single subscriber, you should have different subscription entities created and listened to.
It's worth stating - as it's not obvious from any of the documentation - that each topic should be setup with a subscription for each subscriber.
I.e. if I have 3 subscribers:
/myservicebus/mytopic/mysubscription1
/myservicebus/mytopic/mysubscription2
/myservicebus/mytopic/mysubscription3
I was expecting - probably same as OP - that topics and subscribers were automatically configured as one:many.
Essentially, if multiple subscribers are configured to the same subscription, then this becomes a 'first sub wins' scenario - the same as if it were a queue.
I also ran into this.
I resolved it by making an extra micro service just for forwarding the messages. The forwarder service itself must subscribe to the messages that each of your subscribers must receive. Each Subscriber registers itself (with a unique id) with the event forwarder service (by sending a message to it on startup). The subscribers must then use the message name + the unique id to subscribe to the messages. The message forwarder service will receive the messages and forward them to all the registered subscribers by changing the subject/label of the message (the unique id is added to the subject/label).
This workaround also has it's limitations, there can only be one instance of the message forwarder service or otherwise you have the same problem again. And the message forwarder service must also be running before the other subscribers otherwise it doesn't receive the registrations.

How to subscribe message from Azure service bus topic subscription to web api?

We have multiple webapi(microservices). To communicate between these micro services we are using Azure service bus Topic\Subscription. How webapi controller can get the message subscription so that api can process the message and insert to database. I don't want to use any azure functions. I want subscribe message in my webapi(micro service directly).
You may create a client for the topic to subscribe the message and set the options to complete after the necessary process is done.
please find the below sample code, where you can read the subscription messages from a topic.
you can use WindowsAzure.ServiceBus -Nuget Package
Sample Code:
using Microsoft.ServiceBus.Messaging;
using Microsoft.ServiceBus;
var con = "your connection string for the topic";
var topic = "your topic name";
var subclient = SubscriptionClient.CreateFromConnectionString(con, topic, "yourSubscriptionName");
OnMessageOptions options = new OnMessageOptions();
options.AutoComplete = false;
client.OnMessage(message =>
{
Console.WriteLine("Message:" + message.GetBody<string>());
message.Complete();
}, options);
you may put it in separate method and use as needful.
To poll you may create a webjob, or you can place the code which triggers the web api, so that it will poll the messages at the same time.

Azure Event Hub multiple recipients

I have a server which will need to send messages to several clients to let the clients know that something needs to be done.
I am trying to achieve this by using Azure Event Hub.
I use the following code to send the message:
await eventHubClient.SendAsync(
new EventData(Encoding.UTF8.GetBytes(String.Format("Message {0}, {1}", i, sMessage))),
"1")
.ConfigureAwait(continueOnCapturedContext: false);
await eventHubClient.CloseAsync();
I use two WPF application as listeners which will create the listener at startup and will save the EventProcessorHost in a private variable.
When I send a message it's random which of the listeners will process the message.
Is is possible to send messages to multiple recipients with Azure Event Hub?
You need to put each listener to a separate Consumer Group.
Listeners of the same consumer group are "Competing Consumers", i.e. the first one who takes a lock on an event hub partition wins.

Send push notification to all registered devices with Azure Notification Hub in .NET

I'm working with Azure Notification Hub, and I want to send a push notification message to all registered device in .NET backend. But I'm not sure this way will send to all devices because I don't have the way to check the number of devices received push message.
So, how to, I can send a push message to all devices or can make sure this way is correct?
public static async Task<bool> SendBroadcast(string msg)
{
try
{
var notificationHubClient = NotificationHubClient.CreateClientFromConnectionString(ConfigurationManager.AppSettings["ServiceBusPushNotificationConnectionString"], ConfigurationManager.AppSettings["ServiceBusPushNotificationName"]);
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("message", msg);
param.Add("alert", msg);
var template = new TemplateNotification(param);
var result = await notificationHubClient.SendNotificationAsync(template);
Console.WriteLine(JsonConvert.SerializeObject(result));
return true;
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
return false;
}
}
If you don't specify any tag expression, that means it's broadcast. All devices will receive the notification. You can track how many devices are received through using Per Message Telemetry. Please see below links for same.
https://msdn.microsoft.com/en-us/library/azure/mt608135.aspx
https://azure.microsoft.com/en-us/blog/push-notification-hub-telemetry-expiry-update/
You need to use tags as described in Routing and Tag Expressions:
The only way to target specific registrations is to associate them
with a tag, then target that tag. As discussed in Registration
Management, in order to receive push notifications an app has to
register a device handle on a notification hub. Once a registration is
created on a notification hub, the application backend can send push
notifications to it. The application backend can choose the
registrations to target with a specific notification in the following
ways:
Broadcast: all registrations in the notification hub receive the
notification.
Tag: all registrations that contain the specified tag receive the
notification.
Tag expression: all registrations whose set of tags match the
specified expression receive the notification.
Note, there're limitations on broadcast messages that you need to take into account.
Take a look at the Breaking News App Sample on details about how to use broadcast notifications.

Resources