Real Time Notification System using SignalR and Azure - asp.net

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 the NotificationManager 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.

Yes, your architecture looks like it should do the job, for a load balanced scenario.
If you use ServiceBus Queue it should be, you can integrate pretty easily (use the nuget package SignalRChat Microsoft.AspNet.SignalR.ServiceBus)
Auth will be fine also assuming your application is stateless and auth cookie will still be valid for both roles, assuming they are behind a load balanced scenario.
Service Bus. Here is some more info on how its done. http://www.asp.net/signalr/overview/performance/scaleout-with-windows-azure-service-bus

Related

Microservices client acknowledgement and Event Sourcing

Scenario
I am building courier service system using Microservices. I am not sure of few things and here is my Scenario
Booking API - This is where customer Place order
Payment API - This is where we process the payment against booking
Notification API - There service is responsible for sending the notification after everything is completed.
The system is using event-driven Architecture. When customer places booking order , i commit local transaction in booking API and publish event. Payment API and notification API are subscribed to their respective event . Once Done Payment and notification API need to acknowledge back to Booking API.
My Questions is
After publishing the event my booking service can't block the call and goes back to the client (front end). How does my client app will have to check the status of transaction or it would know that transaction is completed? Does it poll every couple of seconds ? Since this is distributed transaction and any service can go down and won't be able to acknowledge back . In that case how do my client (front end) would know since it will keep on waiting. I am considering saga for distributed transactions.
What's the best way to achieve all of this ?
Event Sourcing
I want to implement Event sourcing to track the complete track of the booking order. Does i have to implement this in my booking API with event store ? Or event store are shared between services since i am supposed to catch all the events from different services . What's the best way to implement this ?
Many Thanks,
The way I visualize this is as follows (influenced by Martin Kleppmann's talk here and here).
The end user places an order. The order is written to a Kafka topic. Since Kafka has a log structured storage, the order details will be saved in the least possible time. It's an atomic operation ('A' in 'ACID') - all or nothing
Now as soon as the user places the order, the user would like to read it back (read-your-write). To acheive this we can write the order data in a distributed cache as well. Although dual write is not usually a good idea as it may cause partial failure (e.g. writing to Kafka is successful, but writing to cache fails), we can mitigate this risk by ensuring that one of the Kafka consumer writes the data in a database. So, even in a rare scenario of cache failure, the user can read the data back from DB eventually.
The status of the order in the cache as written at the time of order creation is "in progress"
One or more kafka consumer groups are then used to handle the events as follows: the payment and notification are handled properly and the final status will be written back to the cache and database
A separate Kafka consumer will then receive the response from the payment and notification apis and write the updates to cache, DB and a web socket
The websocket will then update the UI model and the changes would be then reflected in the UI through event sourcing.
Further clarifications based on comment
The basic idea here is that we build a cache using streaming for every service with data they need. For e.g. the account service needs feedback from the payment and notification services. Therefore, we have these services write their response to some Kafka topic which has some consumers that write the response back to order service's cache
Based on the ACID properties of Kafka (or any similar technology), the message will never be lost. Eventually we will get all or nothing. That's atomicity. If the order service fails to write the order, an error response is sent back to the client in a synchronous way and the user probably retries after some time. If the order service is successful, the response to the other services must flow back to its cache eventually. If one of the services is down for some time, the response will be delayed, but it will be sent eventually when the service resumes
The clients need not poll. The result will be propagated to it through streaming using websocket. The UI page will listen to the websocket As the consumer writes the feedback in the cache, it can also write to the websocket. This will notify the UI. Then if you use something like Angular or ReactJS, the appropriate section of the UI can be refreshed with the value received at the websocket. Until that happens user keeps seeing the status "in progress" as was written to the cache at the time of order creation Even if the user refreshes the page, the same status is retrieved from the cache. If the cache value expires and follows a LRU mechanism, the same value will be fetched from the DB and wriitten back to the cache to serve future requests. Once the feedback from the other services are available, the new result will be streamed using websocket. On page refresh, new status would be available from the cache or DB
You can pass an Identifier back to client once the booking is completed and client can use this identifier to query the status of the subsequent actions if you can connect them on the back end. You can also send a notification back to the Client when other events are completed. You can do long polling or you can do notification.
thanks skjagini. part of my question is to handle a case where other
microservices don't get back in time or never. lets say payment api is
done working and charged the client but didn't notify my order service
in time or after very long time. how my client waits ? if we timeout
the client the backend may have processed it after timeout
In CQRS, you would separate the Commands and Querying. i.e, considering your scenario you can implement all interactions with Queues for interaction. (There are multiple implementations for CQRS with event sourcing, but in simplest form):
Client Sends a request --> Payment API receives the request --> Validates the request (if validation fails throws error back to the user) --> On successful validation --> generates a GUID and writes the message request to Queue --> passes the GUID to the user
Payment API subscribes the payment queue --> After processing the request --> writes to Order queue or any other queues
Order APi subscribes to Order Queue and processes the request.
User has a GUID which can get him data for all the interactions.
If use a pub/sub as in Kafka instead of Kafka (all other subsequent systems can read from the same topic, you don't need to write for each queue)
If any of the services fail to process, once the services are restarted they should be able to pick where they left off, if the services are down in the middle of a transaction as long as they roll back their resp changes you system should be stable condition
I'm not 100% sure what you are asking. But it sounds like you should be using a messaging service. As #Saptarshi Basu mentioned kafka is good. I would really recommend NATS - although I'm biased because that's the one I work with
With NATS you can create request-reply messages to interface between client and booking service. That's a 1-1 communication
If you have multiple instances of each of your services running, you can use the Queuing service to automatically load balance. NATS will just randomly select a server for you
And then you can use pub-sub feeds for communication between all of your services.
This will give you a very resilient and scalable architecture, and NATS makes it all incredibly easy

loose coupling of notifications in SOA

The solution is composed of an orchestration process services and multiple legacy applications in charge of making CRUD operations on the domain entities.
Every time an update, add or delete statement is executed by these legacy applications a notification is sent by the entity owner application.
In the modeling phase we decided to map the entities fine-grained. In this way every CRUD operation can rise thousands of notifications(up to 20k) resulting to blocking users activity for a while becouse entity persistence and notification sending are combined in the same transaction. This can be inacceptable when it takes more than 120 seconds.
What i wanted to do is separate the user activity in legacy applications from entity persistence and notification sending deferring these to a specific application service(for example). I know the best would be deferring these activities to a background thread in the user application but as i mentioned i'm using very old legacy applications. Is there any SOA design patterns that can be applied to this scenario?
What you want is "Decoupled invocation". You accept the request and put it in a (persistent) queue and send an acknowledgment to the user that the request has been received. Depending on the scenarioYou can send an additional reply (e.g. by email) when the message has been fully processed.
.

SignalR - Handling disconnected users

Hy,
I'm using the signalR library on a project to handle an notification and chat modules. I've a table on an database to keep a track of online users.
The HUB for chat is inheriting IDisconnect where i disconnect the user. After disconnecting the user, i warm the users about that event. At this point, i check if the disconnect user is the client. If it's, then i call an method on HUB to reconnect the user (just update the table).
I do this because with the current implementation, once the user closes a tab on the browser it calls the Disconnect task but he could have another tab opened.
I've not tested (with larger requests) this module yet, but on my development server it could take a few seconds between the IDisconnect event, and the request from the user to connect again.
I'm concerned with my implementation to handle disconnected users from the chat but i can't see another way to improve this.
If possible, could someone give me a advice on this, or this is the only solution that i've?
Update: I ended up using a singleton class to store all the users and their connections id from signalr. This way i can get the id from user during the disconnect task (at this point you don't have any httpcontext to get the user information, but you can always get the user id with the connection id of signalr from the array in the singleton class).
20-02-2013 Although the above solution was doing the job, i had the need to scale my project. My solution was to use Redis to store all user connections, and take benefit of key expiration time on disconnect events. During the reconnect i check if the key is in pending state (gonna expire in a few minutes).
You can check out how JabbR, a multi-room chat application built on top of SignalR, solves this problem: https://github.com/JabbR/JabbR/blob/master/JabbR/Hubs/Chat.cs
It basically keeps a 1:N mapping of User<->ConnectionId, so when the last connection is disconnected the user can be marked as "offline".

Check database for changes via long polling

Im creating a chat app in ASP.NET MVC3.
im using long polling and AsyncController to do so
when a user posts a chat its saved in database , to retrieve should i constantly check database for change in record or after definite interval
or is there an better/ efficient way of doing it
i came across this question but could not get a usable answer.
You may take a look at SignalR for an efficient way. Contrary to the standard polling mechanism (in which you are sending requests at regular intervals to check for changes), SignalR uses a push mechanism in which the server sends notifications to connected clients to notify them about changes.
Since you're already using long polling and an asynccontrolller, why not create a message pool? Take a look at this solution.
In a nutshell, instead of just writing the updated chat to the database, you should also stick it in some sort of queue. Then each user's async thread is listening to that pool waiting for a message to appear. When one appears return the data to the user through your normal operation. When all listening threads have picked up the message it can be removed from the queue. This will prevent you from having several threads hammering your database looking for a new message.
You can give PServiceBus(http://pservicebus.codeplex.com/) a try and here is a sample web chat app(http://74.208.226.12/ChatApp/chat.html) running and does not need database in between to pass message between two web clients. If you want to persist data in the database for logging sake, you can always subscribe to the chat message and log it to database.

Communication between multiple web applications using SignalR

I have two different web applications that need to communicate with each others (which I can currently accomplish by using Silverlight Duplex but that doesn't scale very well). After reading about SignalR, I'd like to give this a try but failed to find much documentation on how to do this. Any advice on ho to get started would be greatly appreciated.
Thanks!
More specific Info:
Example:
Application A (Bidding Interface) - A web page to allow multiple end-users to place bids on certain items.
Application B (Managing Interface) - A web page to allow a user (or could potentially be multiple users) to monitor/control the actions from Bidding Interface.
So when a user from Application A place a bid on a piece, I'll need a way to alert Application B that a bid has been placed. Then from Application B, should the user choose to accept the bid, I need to send an alert back to Application A (to update current price, increase bid etc...)
In all honesty, in might just be simpler to have each application push the notifications to each other via standard service calls (WCF, ASMX, HTTP handler endpoints, MVC controllers, whatever). SignalR is useful in browser to server communications because there isn't a consistent way to do push from the server to a connected browser. But from web app to web app pushing is simple; Application A just calls a service endpoint on Application B to notify it of something happening.
Assuming that what you want is something like ...
User (browser) --- Application A --- Application B --- User (Browser)
Realtime communication can be done by doing the following ...
This isn't the job of signalR however something like NServiceBus would fit this very well.
you reference a bus dll file and hubs can both raise and respond to events.
In your case you would have both SignalR and your Service Bus technology work together to allow the cross application sync.
So the process is something like ...
User in application A fires up browser and requests page.
Application A creates Hub instance which internally subscribes to Service Bus events
User in application B fires up browser and requests page.
Application B creates Hub instance which internally subscribes to Service Bus events
User on either application does some action resulting in SignalR picking up a message.
SignalR raises bus event to say "This user did something" on the service bus.
Other Hub on other Application through subscribription to the event gets notified of the event and takes any action to inform its connected users of it.
Lesson to be learnt here ...
Don't try and make a technology do something beyond its purpose ... use the right tool for the job.
This entire solution can be done with little more than about 20 lines of code after getting the core framework setup.
NServiceBus can be found here:
http://particular.net/nservicebus
Disclaimer: There may be other solutions but this one suggestion don't assume this is the only way this can be solved, and the only technologies that be used in this manner.
I am not affiliated in any way with Particular or the NServiceBus product.

Resources