从Azure Worker角色发送通知到Azure Web角色 - 最佳实践

时间:2011-08-30 09:32:41

标签: lucene azure lucene.net azure-worker-roles azure-web-roles

场合

用户可以上传Documents,一个队列消息将被放入带有文件ID的队列中。工作者角色将选择此并获取文档。用Lucene完全解析它。解析完成后,应更新Webrole上的Lucene IndexSearcher。

在Web角色上我保留了一个静态的Lucene IndexSearcher,因为否则你必须在每个搜索请求中创建一个新的IndexSearch,这会带来很多开销等。

我想要做的是从工作者角色发送通知,以便更新他的IndexSearcher所需的Web角色。

可能的解决方案

  • 制作某种通知队列。 Web角色启动无休止的任务,不断检查通知队列。如果他找到了消息,那么他应该更新IndexSearch。
  • 在辅助角色上启动WCF服务并与Web角色连接。从Worker Role进行回调,并通过服务告诉Web角色他需要更新他的IndexSearcher。
  • 只需定期更新

什么是最好的解决方案,还是有其他解决方案?

非常感谢!

2 个答案:

答案 0 :(得分:2)

如果您的工作者角色使用类似(DateTime.MaxValue - DateTime.UtcNow).Ticks.ToString("d19")的PK将每个完成的作业的详细信息写入表中,您将获得已处理的最新作业的排序列表。设置您的Web角色以轮询表格,如下所示:

var q = ctx.CreateQuery<LatestJobs>("jobstable")
    .Where(j => j.PartitionKey.CompareTo(LastIndexTime.GetReverseTicks()) < 0)
    .Take(1)
    .AsTableServiceQuery()

if (q.Count() > 0)
{
    //new jobs exist since last check... re-index.
}

对于执行索引编制工作的辅助角色,这很好,因为他们可以不加思索地写入表而不用担心冲突。对于您,您还有他们正在处理的作业的审核日志(假设您在其中放置了一些详细信息)。

但是,您还有一个问题:听起来您有1个更新索引的Web角色。这个Web角色当然可以根据您选择的频率轮询此表(只需跟踪LastIndexTime以便稍后搜索)。如果您有多个Web角色,那么您的问题是如何控制Web角色的并发性。每个Web角色是否都维护自己的索引,或者您是否已将其存储在某个地方?对不起,但是如果这很明显的话,我不是Lucene的专家。

无论如何,如果您的WebRole中有多个实例,并且所有人都可以看到一个索引,则需要防止多个角色反复更新索引。您可以通过租用索引(如果存储在blob存储中)来执行此操作。

根据评论进行更新:

如果每个WebRole实例都有自己的索引,那么您不必担心租赁。只有当他们一起共享blob资源时才会这样。因此,这种技术应该可以正常工作,并且唯一可能的障碍是Web角色的轮询间隔可能略微不同步,导致所有更新之前的结果会有所不同(取决于您点击的实例)。在桌子上每30秒轮询一次,这将是你最大的不同步。每个Web角色实例只需跟踪上次更新并从该点进行增量搜索。

答案 1 :(得分:1)

根据上传频率,您可能会发现队列消息导致您不必要的更新。例如,如果您收到十几个上传并在近距离处理它们,那么您现在有十几个队列消息,每个消息都告诉您的Web角色要更新。保留单个信号(可能是表行或SQL Azure行)会更有意义。您可以简单地将行值设置为1,表示需要更新。当您的Web角色检测到此更改时,请重置为0并开始更新。注意:如果使用Azure表行,则需要轮询更新(并且根据流量,您可以开始累积大量事务)。您也可以将AppFabric Cache用于此信号。

您可以在Web角色的内部端点上使用WCF服务。但是,您仍然遇到突发问题(如果您在webrole更新时获得了十几个上传内容,那么您不希望再进行其他更新)。