Hi,
I have an ASP.NET Module Zero application (ASP.NET Core targetting .NET 4.6) that runs on multiple servers. The servers are behind a load balancer.
The application publishes a notification. The application is configured to use Redis (and it's pub/sub model) as a backplane. The idea here is that the notification from the server gets written to the Redis backplane, the Redis backplane then notifies all the other servers (that are Redis subscribers) and the other servers then using the ABP Zero notification system send the notification to all it's connected clients using SignalR.
Publishing the notification is ok and it gets written/published to the Redis backplane. All servers/subscribers get the Redis message ok (I can see it using redis-cli). The problem I have is that only the clients connected to 1 server get a SignalR message to act on (e.g. display a model and update the notification count in the top right corner).
I know this is a needle in a hay stack, but am I missing some obvious configuration step that would cause this?
Thanks
Kevin
10 Answer(s)
-
0
Hi,
Notifications are sent by background jobs. If you have a web farm, you probably run background jobs only in one server. Because otherwise, background jobs may be executed per server which causes problems.
Is that true for your case?
Did you handle Redis backplane yourself? Is it integrated to SignalR?
-
0
Thank you for your reply.
I will have to read up on ABP back ground jobs.
For the backplane, I have a Redis installation and I have simply configured ABP to use it. I haven't made any SignalR changes yet.
private void ConfigureOwinServices(IAppBuilder app) { app.Properties["host.AppName"] = "Phone"; app.UseAbp(); // configure SignalR to use Redis backplane GlobalHost.DependencyResolver.UseRedis(_redisConnString, 6379, "", "PhonePbx"); app.MapSignalR(); }
Then, as per documentation on notifications, I create a notification in AppNotifier class
public async Task IncomingCallAsync(string ddi, string cli) { await _notificationPublisher.PublishAsync( AppNotificationNames.IncomingCall, new MessageNotificationData($"New incoming phone call to {ddi} from {cli}"), severity: NotificationSeverity.Success ); }
I haven't had to change any client side code as this is already built in to ABP/Metronic.
Is this the correct approach. I have a web form behind a load balancer. When I raise a notification I want all clients to receive the notification, which means all servers will have to use SIgnalR to push the notification to their clients.
-
0
You are sending notification to subscribed users for the current tenant. Did you subscribe to notifications for all users?
-
0
Yes, all users are subscribed. I think the back plane is working. I am now using my own version of SignalRRealTimeNotifier as I think the issue may be here.
-
0
@devkev2403, does your notification depend on a permission ?
-
0
I think I have solved this. The problem is a limitation in the OnlineClientManager. The SignalRRealTimeNotifications class that is used to send SignalR message uses the OnlineClientManager to determine who should get the notification and what the SignalR connection id is. However, the OnlineClientManager is only aware of clients connected to the server it is running on, not the entire web farm.
To fix this I am moving the dictionary used by the OnlineClientManager into Redis. It's not finished but so far so good.
-
0
@devkev2403 Thanks for the feedback.
-
0
@devkev2403
Is there any chance you can share the codes for your new OnlineClientManager?
Regards, Gunpal Jain
-
0
Unfortunately the code isn't mine to share as it belongs to my employer, however, let me see what I can do, as we do like to give back to the community when we can.
-
0
If they don't let you post any code, maybe you could just describe your solution so maybe we can take a stab at it. Then you could maybe review our code :)