I am trying to craft a facebook-like notification system in our ASP.NET MVC website
In a scenario, the notification system works like this
- User1 follow User2 by clicking the follow button in the MVC site
- the MVC site send a
NotificationItem
to theNotificationManager
via API request.
POST api/notifications/send
NotificationManager
then process this notificationItem and then save it to Azure Table Storage
class NotificationManager { void SaveNotification(NotificationItem item) { // save it to azure table storage } }
After saving item, the Client (User2) then subscribe to the notificationEvent via the
NotificationHub
(SignalR hub)NotificationHub
then notify User2 along with the processed notification data.
class NotificationHub: Hub { async Task NotifyUser(string recipientId) { // query data from storage and then process it var notificationData= await _repo.GetProcessedNotificationDataAsync(recipientId); Clients.Group(recipientId).notifyUser(notificationData); } }
I tried to illustrate the CURRENT process and the architecture on this image
Now, the one that bothers me is this line of code in step number 5
var notificationData= await _repo.GetProcessedNotificationDataAsync(recipientId);
What it does behind is query the notificationItem
from storage, process it to user readable notification (ei. "User1 is now following you"), then update the status of the notificationItem
(IsSent, DateSent) behind.
Needless to say, it performs somehow "heavy" operation. And it will be triggered in real-time every time there is a new NotificationItem to be delivered or broadcast to each subscriber.
Obviously, im talking about performance and scalability issue here. So I researched some possible technology or approach that can solve this problem. And seems like using Azure Service Bus backplane approach is a viable option
SignalR Scaleout with Azure Service Bus
Introduction to Scaleout in SignalR
One particular paragraph explains some limitations on this approach
Server broadcast (e.g., stock ticker): Backplanes work well for this scenario, because the server controls the rate at which messages are sent.
Client-to-client (e.g., chat): In this scenario, the backplane might be a bottleneck if the number of messages scales with the number of clients; that is, if the rate of messages grows proportionally as more clients join
High-frequency realtime (e.g., real-time games): A backplane is not recommended for this scenario.
Now - this one got me thinking, as in my case. Server Broadcast and Client to Client (and something in between) is applicable to what I am trying to achieve.
These are the notification event scenarios that I am currently working on (and its acceptance criteria)
- Notify user for new followers (real-time or near-real-time notification)
- Chat Messaging (real-time, will see if the chatter is currently typing)
- Post a Status (real time or near real time)
- Comment in a Post (real-time, will see if the chatter is currently typing)
After hours of thinking - What's in my mind right now (as a result of my lack of experience) is a
notification system something like this
As you will notice, this is very different from our current design. The current design only uses 1 Azure webrole.
In this, theres a webrole
for the website, webrole for the hub, and a worker role to process the notification data. Therefore - distributing the "load" to 3 different roles as well as opening the possibility for scaling-out.
Now - this is my questions in my head right now.
- Is this architecture right for what I am trying to achieve?
- Since the notification is in the queue - can we achieve "Real-time" notification update on this?
- Since we separate the SignalR hub in another web role - how we will handle authorization?
- Service Bus Queue or Azure Queue?
Any help will be appreciated.
Note: I intend to only use Azure technologies as this project is really an Azure and .NET oriented.