在ASP.NET应用程序和工作者角色之间进行通信的最佳方式

时间:2012-08-21 21:31:13

标签: asp.net-mvc wcf azure azure-worker-roles azure-web-roles

我同时设置了ASP.NET应用程序和工作者角色,现在我想知道如何在它们之间进行通信?我认为这个想法是解决方案将分布在不同的地理位置。那么如何以简单有效的方式链接分布式Worker和Web角色呢? 我已经开始研究WCF,但它看起来像是一个过度杀伤和过于复杂的东西。我的另一个想法是使用Worker角色内的SignalR客户端与Web角色中的服务器进行通信。

修改

具体情况:

1)用户将文件上传到服务器

2)服务器将文件发送到Azure存储并将文件名添加到CloudQueue

3)Worker从CloudQueue

获取文件名

4)Worker启动一个新的Thread,它从Azure Storage获取文件并开始处理它

5)工作人员/线程在文件处理的每一步报告回应用程序

6)应用程序接收报告并使用SignalR将处理步骤实时转发到客户端的浏览器。

我缺少的是步骤2> 3,如何立即通知工人新文件已到达?我不想轮询CloudQueue,因为它会造成延迟。 同样在步骤5> 6,工作人员需要通知应用程序有关步骤,这应该没有延迟,但我再也看不到在这种情况下如何使用轮询解决方案。

3 个答案:

答案 0 :(得分:1)

如上所述,需要更多的上下文。您基本上有两个主要选项,Windows Azure队列和Windows Azure服务总线队列/主题。我的个人建议是,如果Web和工作者角色位于同一区域,则使用Azure队列,如果不是,则使用服务总线队列。我不得不问你为什么不将你的Web和工作者角色放在一起,如果你有地理部署你的应用程序然后看看在每个区域部署所有的Web角色和工作角色,例如美国,欧洲和美国亚洲然后使用流量管理器将用户路由到最佳区域。

有一篇关于何时使用哪个队列'Windows Azure队列和Windows Azure服务总线队列 - 比较和对比'的博客文章:http://msdn.microsoft.com/en-us/library/windowsazure/hh767287.aspx

HTH

修改

下面是一个很好的Web和工作者角色通信方法(我从@smarx最近回答的一个帖子中偷了这个)

1 Web角色将消息写入包含作业ID的队列。

2 Worker角色完成工作并将结果写入带有分区键的表。

3 Web角色正在轮询该表的那一行。一旦它存在,答案就会回来。

在您的情况下,您可以让工作者角色使用状态更新来更新表存储,然后让您的Web角色选择它们并将其显示给用户。例如20%,50%,完成等...

只要您从Web角色中充分轮询(*注意交易成本),我就不会看到此类通信的延迟

我认为可以在这里进行某种角色间的通信以进行状态更新,但这可能是过度的IMO:

http://msdn.microsoft.com/en-us/library/windowsazure/hh180158.aspx

答案 1 :(得分:0)

我建议您查看CQRS,它代表Command Query Responsibility Segregation。

这种架构的目的是创建松散耦合,可扩展和可扩展的系统。

http://cqrsjourney.github.com/

Greg Young发明了这个系统,并且有许多开源实现可用于加速分布式可扩展系统的构建。在他之前是Bertrand Meyer,他奠定了基础。

过度简化的概念是一系列队列将Web角色和工作者角色分开。因此,当用户从Web角色提交工作时,该工作将排队,然后由工作人员角色选择。权衡是最终的数据一致性,而不是直接的一致性。它的好处是松散耦合和可扩展。如果队列开始变得太大,可以添加额外的工作者角色来处理额外的规模。

该方法使用命令,查询,域对象等概念。 CQRS正在成为实现我认为您正在寻求的目标的极其强大的方式。

搜索引擎可以为您提供许多优质资源。以下是一些有用的视频: 格雷格杨 http://www.youtube.com/watch?v=KXqrBySgX-s 我的朋友Rinat http://www.youtube.com/watch?v=CnvO_nlvrps

祝你好运!

答案 2 :(得分:0)

我使用azure表存储作为工作者角色和Web角色之间进行通信的地方。基本上,Worker角色会将消息/通知存储到azure表中,而web角色将有一个定时器来定期检查azure表中的更改。之后,该Web角色将使用SignalR实时向客户端页面发送消息,以报告进度。

Global.asax.cs文件:

private static System.Timers.Timer _timer;

protected void Application_Start()
{
     //Start the timer job
     _timer = new System.Timers.Timer(3000);
     _timer.Elapsed += new ElapsedEventHandler(WebRoleTimerJob);
     _timer.Start();
}


/// <summary>
/// This event will be fired intervally every 3 seconds to broadcast messsage to all registered client pages using SignalR
/// </summary>        
public static void WebRoleTimerJob(object sender, ElapsedEventArgs e)
{               
      // Here, you can read Azure table storage to detect any changes    
      // or notification from Worker role
      // ....

      //If there is any changes, then broadcast message 
      // to all relevant client pages using SignalR   

      var context = GlobalHost.ConnectionManager.GetHubContext<Hub>();       
      context.Clients.All.addNewMessageToPage("your_message_name", "message_content");
}