我正在尝试在我们的 ASP.NET MVC 网站中制作一个类似 facebook 的通知系统
在一个场景中,通知系统是这样工作的
- User1 通过单击 MVC 站点中的关注按钮关注 User2
- MVC 站点通过 API 请求发送
NotificationItem
一个NotificationManager
。
POST api/通知/发送
NotificationManager
然后处理此 notificationItem 然后将其保存到 Azure 表存储
class NotificationManager { void SaveNotification(NotificationItem item) { // save it to azure table storage } }
保存项目后,客户端(User2)然后通过
NotificationHub
(SignalR hub)订阅notificationEventNotificationHub
然后通知 User2 以及处理后的通知数据。
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); } }
我试图在这张图片上说明当前流程和架构
现在,困扰我的是第 5 步中的这行代码
var notificationData= await _repo.GetProcessedNotificationDataAsync(recipientId);
它背后的作用是查询notificationItem
来自存储,将其处理为用户可读的通知(例如“User1 现在关注你”),然后更新notificationItem
后面的 (IsSent, DateSent) 的状态。
不用说,它以某种方式执行“繁重”操作。并且每次有新的 NotificationItem 发送或广播给每个订阅者时都会实时触发。
显然,我在这里谈论性能和可扩展性问题。所以我研究了一些可以解决这个问题的可能的技术或方法。似乎使用 Azure 服务总线背板方法是一个可行的选择
一个特定的段落解释了这种方法的一些限制
服务器广播(例如股票行情):背板在这种情况下工作得很好,因为服务器控制发送消息的速率。
客户端到客户端(例如,聊天):在这种情况下,如果消息数量随客户端数量增加,那么背板可能会成为瓶颈;也就是说,如果消息的速率随着更多客户端的加入而按比例增长
高频实时(例如实时游戏):不建议在这种情况下使用背板。
现在 - 这个让我思考,就像我的情况一样。服务器广播和客户端到客户端(以及介于两者之间的东西)适用于我想要实现的目标。
这些是我目前正在处理的通知事件场景(及其接受标准)
- 通知用户有新的关注者(实时或近实时通知)
- 聊天消息(实时,将查看聊天者当前是否正在输入)
- 发布状态(实时或接近实时)
- 在帖子中评论(实时,将查看聊天者当前是否正在输入)
经过数小时的思考 - 我现在(由于我缺乏经验)的想法是一个类似这样的通知系统
您会注意到,这与我们当前的设计非常不同。当前设计仅使用 1 个 Azure webrole。
其中,有一个webrole
用于网站,webrole 用于中心,以及一个工人角色来处理通知数据。因此 - 将“负载”分配给 3 个不同的角色,并为scaling-out.
现在 - 这是我现在脑海中的问题。
- 这种架构是否适合我想要实现的目标?
- 由于通知在队列中 - 我们可以实现“实时”通知更新吗?
- 由于我们将 SignalR 集线器分离到另一个 Web 角色中 - 我们将如何处理授权?
- 服务总线队列还是 Azure 队列?
任何帮助将不胜感激。
注意:我打算只使用 Azure 技术,因为这个项目实际上是面向 Azure 和 .NET 的。