Azure Event Hub multiple recipients - azure

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.

Related

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

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"
}));

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.

Azure Servicebus: Receive all the message from one session id of a queue

I have 2 question for which I failed to find any solution.
Is there any built in way in azure service bus queue, where I can receive messages only from one session (for that sessionId) in my session handler.
Also is there any way I can receive messages only from the deadlettered queue for that session alone.
I can do this programmatically in my code, but I don't want to write if else logic in my code.
Is there any built in way in azure service bus queue, where I can receive messages only from one session (for that sessionId) in my session handler.
As Sean Feldman mentioned Queue​Client.​Accept​Message​Session​Async(sessionID) allows to achieve that for a normal queue.
If want to use Queue​Client.​Accept​Message​Session​Async(sessionID) to receive queue message, we need to create the with RequiresSession true,
var description = new QueueDescription(QueueName) 
{ 
    RequiresSession = true 
}; 
namespaceManager.CreateQueue(description);
Also is there any way I can receive messages only from the deadlettered queue for that session alone.
Base on my test we can't get the dead-letter queue message from the deadletter queue with following code
var dlqName= QueueClient.FormatDeadLetterPath(queueName);
var dlqClient = QueueClient.CreateFromConnectionString(connectionstring, dfQueue);
var gid = Guid.NewGuid().ToString();
var messageSession = client.AcceptMessageSession(gid);
var receiveMessage = messageSession.Receive();
Cannot create a MessageSession for a sub-queue. TrackingId:06a39820-7bf6-412d-ab31-80ef5c174a12_G20_B31, SystemTracker:tomsbservice:Queue: queuename |$DeadLetterQueue
My workaround is that we could get the dead-letter queue message and submit to queue or another normal queue.
I don't think you can do that for Service Bus queues. You can archieve something similar with Service Bus topic and filtered subscription.
So, you send your messages to a topic, and then you'd have to create a subscription per session ID similar to this:
var filter = new SqlFilter(#"sys.SessionId = \"SESSIONID\"");
namespaceManager.CreateSubscription("YOUR_TOPIC", "SESSIONID_SUBSCRIPTION", filter);
and then just receive messages from this subscription:
var client = new SubscriptionClient("...", "YOUR_TOPIC", "SESSIONID_SUBSCRIPTION");
var message = client.Receive();
Message Sessions feature is specifically designed for that.
Queue​Client.​Accept​Message​Session​Async(sessionID) allows to achieve that for a normal queue.
As for the DLQ - not sure if that works.

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.

Why use a QueueClient vs MessageFactory?

In Azure Service Bus, you can send a brokered message using QueueClient and MessageFactory. I would like to know why would you want to use one over the other.
Azure Service Bus provides different way to send/receive messages.
You can use the QueueClient to send and receive message to/from a queue.
You can use the TopicClient to send message to a topic
And you can use the SubscriptionClient to receive message from a subscription.
Using MessageSender and MessageReceiver, you create sender and receiver that are entity type invariant:
var factory = MessagingFactory.CreateFromConnectionString("MyConnectionString");
A MessageSender can send messages to both topic or queue:
var sender = factory.CreateMessageSender("Queue ou topic path");
A MessageReceiver ca receive messages from both queue and subscription:
var receiver = factory.CreateMessageReceiver("Queue ou subscription path");
Theses abstractions can give you more flexibility if you need to switch from a queue to a topic or vice versa because you just need to change the path of the service bus entity (This could be in your configuration file) so no code change needed. Using QueueClient, TopicClient, SubscriptionClient, you'll have to change your code if you want to move from a queue to a topic.
So my advice is to always use a MessageReceiver/MessageSender when you have to send/receive message from/to a an Azure ServiceBus queue topic/subscription.
NOTE: This does not apply for Eventhub which has a different implementation.

Resources