使用 SignalR 从 Azure 工作者角色向客户端发送消息
Using SignalR to send message to client from Azure Worker Role
我正在处理一个 ASP.net MVC 云服务项目 运行 两个角色,一个网络角色和一个辅助角色。 Web 角色中的其中一个页面发起构建 APK 文件的请求,在服务器上构建 APK 文件可能需要 1-5 分钟。所以我们想出了以下流程:
- 用户在页面上启动 APK 构建过程。
- 请求被路由到我们的 mvc 操作,在 Azure 存储队列上创建一条新消息。
- Worker 角色始终从队列中轮询并启动 APK 构建过程。现在 APK 已准备就绪,我们希望通过以下方式通知用户:
(a) 发送电子邮件,现在可以使用。 (b) 使用 SignalR 在页面上通知用户。
我们现在的问题是在SignalR部分,我们如何在页面上通知用户APK已经准备好,他可以下载了。
编辑 - 为了完整起见复制第一条评论的内容 -
我又看了一遍这个问题,我知道你正在使用辅助角色来轮询队列。在这种情况下,您可以使您的工作角色成为 .Net SignalR 客户端,该客户端连接到 web 角色上的 APK signalR 中心。 Web 角色上的 signlaR 集线器可以简单地将它从 .Net 客户端接收到的任何消息转发到 javascript 客户端(浏览器)。
我建议浏览以下链接
Hubs API Guide - Server
Hubs API Guide - Javascript Client
在完成其余答案之前。
从上面两个链接可以了解到,SignalR使服务端能够'push'数据到客户端。为了实现这一点,您需要做两件事 -
- signalR 集线器 - 这是 'hub' 客户端可以订阅以接收消息的集线器。
- 连接到集线器的客户端
服务器上的 signalR 集线器可能看起来像这样 -
public class APKHub : Hub
{
public async Task JoinGroup(string groupName)
{
await Groups.Add(Context.ConnectionId, groupName);
Clients.Group(groupName).sendMessage(Context.User.Identity.Name + " joined.");
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
public void NotifyUser(string userId)
{
this.Clients.Group(userId).notify();
}
}
在客户端,您的代码可能如下所示 -
var notificationHandler = function () {
var url;
var user;
var init = function (notificationUrl, userId) {
url = notificationUrl;
user = userId;
connectToAPKHub();
}
var connectToAPKHub = function () {
$.connection.hub.url = url;
var apk= $.connection.apkHub;
apk.client.notifyUser = function (user) {
console.log(user);
}
apk.client.addMessage = function (message) {
console.log(message);
}
$.connection.hub.start().done(function () {
console.log('connected to apkhub');
apk.server.joinGroup(user);
})
}
return {
init: init
}
}();
notificationUrl 是 signalR 服务器正在侦听的 URL。
这会在服务器上设置您的基本集线器,您现在应该能够将您的客户端连接到 signalR 集线器。构建 APK 后,您可以使用以下代码(将其放置在任何地方 - 例如 - 在控制器操作中)实际将消息推送到相关客户端 -
var apkHub = GlobalHost.ConnectionManager.GetHubContext<APKHub>();
apkHub.Clients.Group(groupName).notifyUser(groupName);
组名可以是唯一标识用户的标识符。
希望对您有所帮助。
我正在处理一个 ASP.net MVC 云服务项目 运行 两个角色,一个网络角色和一个辅助角色。 Web 角色中的其中一个页面发起构建 APK 文件的请求,在服务器上构建 APK 文件可能需要 1-5 分钟。所以我们想出了以下流程:
- 用户在页面上启动 APK 构建过程。
- 请求被路由到我们的 mvc 操作,在 Azure 存储队列上创建一条新消息。
- Worker 角色始终从队列中轮询并启动 APK 构建过程。现在 APK 已准备就绪,我们希望通过以下方式通知用户: (a) 发送电子邮件,现在可以使用。 (b) 使用 SignalR 在页面上通知用户。
我们现在的问题是在SignalR部分,我们如何在页面上通知用户APK已经准备好,他可以下载了。
编辑 - 为了完整起见复制第一条评论的内容 -
我又看了一遍这个问题,我知道你正在使用辅助角色来轮询队列。在这种情况下,您可以使您的工作角色成为 .Net SignalR 客户端,该客户端连接到 web 角色上的 APK signalR 中心。 Web 角色上的 signlaR 集线器可以简单地将它从 .Net 客户端接收到的任何消息转发到 javascript 客户端(浏览器)。
我建议浏览以下链接
Hubs API Guide - Server
Hubs API Guide - Javascript Client
在完成其余答案之前。
从上面两个链接可以了解到,SignalR使服务端能够'push'数据到客户端。为了实现这一点,您需要做两件事 -
- signalR 集线器 - 这是 'hub' 客户端可以订阅以接收消息的集线器。
- 连接到集线器的客户端
服务器上的 signalR 集线器可能看起来像这样 -
public class APKHub : Hub
{
public async Task JoinGroup(string groupName)
{
await Groups.Add(Context.ConnectionId, groupName);
Clients.Group(groupName).sendMessage(Context.User.Identity.Name + " joined.");
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
public void NotifyUser(string userId)
{
this.Clients.Group(userId).notify();
}
}
在客户端,您的代码可能如下所示 -
var notificationHandler = function () {
var url;
var user;
var init = function (notificationUrl, userId) {
url = notificationUrl;
user = userId;
connectToAPKHub();
}
var connectToAPKHub = function () {
$.connection.hub.url = url;
var apk= $.connection.apkHub;
apk.client.notifyUser = function (user) {
console.log(user);
}
apk.client.addMessage = function (message) {
console.log(message);
}
$.connection.hub.start().done(function () {
console.log('connected to apkhub');
apk.server.joinGroup(user);
})
}
return {
init: init
}
}();
notificationUrl 是 signalR 服务器正在侦听的 URL。
这会在服务器上设置您的基本集线器,您现在应该能够将您的客户端连接到 signalR 集线器。构建 APK 后,您可以使用以下代码(将其放置在任何地方 - 例如 - 在控制器操作中)实际将消息推送到相关客户端 -
var apkHub = GlobalHost.ConnectionManager.GetHubContext<APKHub>();
apkHub.Clients.Group(groupName).notifyUser(groupName);
组名可以是唯一标识用户的标识符。
希望对您有所帮助。