我有以下设置:部署了N个Azure Worker角色实例。我们的桌面应用程序向Azure上传一条消息,然后上传一组与消息相关的图像。信息知道它需要什么图像。
这两个活动(消息上传和图像上传)是独立的--图像可以在用户生成消息之前上传(称为缓存--但更复杂),或者在消息上传到Azure之后的几秒钟/分钟。
我将消息存储在Azure MSSQL数据库中,图像存储在blobs中,对它们的URL存储在数据库中。还有MessageToImage表,它为消息存储指向图像的链接。下面是一个简化的DB结构(请原谅我的C#):
class Message
{
public int Id;
public string Text;
}
class Image
{
public int Id;
public string Name;
public string BlobUrl; // Null if image was not received by the service yet
}
class MessageToImage
{
public int MessageId;
public List<int> ImageIds;
}
当我们准备好所有图片的信息(即所有的图像都上传完毕)时,我们需要做一些其他的事情(比如,在Facebook上发布)。这里的问题是:如何保证消息只处理一次?在最坏的情况下,我将让N个实例同时接收该消息的N个图像--哪个实例将“选择”将消息发送到进一步处理?我怎么能保证只发生一次呢?
到目前为止,我提出了以下想法:
还有其他的想法/建议吗?
谢谢!
UPDATE1 @Richard和@Rob建议使用服务总线队列。我确实调查过了。我仍然没有答案的部分是,决定何时将消息发送到队列以进行处理的WORKER角色中的代码应该是什么样的呢?只有当数据库/blobs中存在所有图像时(即上传到Azure云中),消息才会发送到队列中。在这里,我仍然想指出我的角落案例-我有10个图像同时处理10个工人的角色。对于所有实例,处理同时结束。每个角色用上传的图像URL更新数据库。然后,我应该以某种方式触发最终消息处理--这意味着其中一个实例应该获得优先级。我不清楚我该怎么做。
希望这能让我的问题更清晰些。
发布于 2013-05-22 23:47:12
创建Azure服务总线队列,并让客户端应用程序向队列发送消息。然后,您的工作角色可以从队列中提取消息并处理这些消息。
服务总线队列最重要的一点是,它们保证消息只能从队列中取出一次,因此消息被标记为“被获取”。如果未将事务标记为在(可配置的)时间段内完成,则消息将返回到队列,以便由下一个工作人员请求提取。
这意味着,如果您的worker角色在处理过程中失败,消息最终将重新出现在队列中,由下一个工作人员来获取它,并(希望)完成所需的工作。
有关更多信息,请阅读此链接:
如何使用服务总线队列
发布于 2013-05-23 00:13:47
您应该考虑使用服务总线消息传递会话
在您的客户端上,为上传会话生成唯一的批处理上传Id (使用GUID而不是int)。上传的每个图像都应该附有这个Id (上传批次中所有图像的Id相同)。当您的服务接收到图像时,它会将一个“上传图像”BrokeredMessage发布到服务总线队列或主题中,并将SessionId设置为客户端提供的唯一Id。
当您的消息从客户端发送到服务时,使用它发送批处理上传Id。当从服务发布中接收到这一点时,另一个队列/主题上会出现一个"Process“BrokeredMessage。此BrokeredMessage的接收方将读取批处理上传Id,然后开始侦听与相关sessionId相关的所有“上传图像”消息。它可以继续这样做,直到它已经接收到它们全部(可能需要发送一个总上传计数,以便它知道什么时候停止)。一旦收到它们,它就可以生成一个新的BrokeredMessage来触发图像上传的处理(例如向facebook发布帖子)。
您希望为最终处理阶段(post到facebook)生成一个独立的BrokeredMessage,以便如果您的角色在处理消息时失败,消息将在稍后重新传递。
要记住的是,消息“至少收到一次”,如果您的角色在处理消息过程中中途失败,则消息将在超时后返回到队列/主题。因此,您的处理逻辑需要能够处理它正在处理之前已经部分处理过的消息的情况。
以下是不同的行为者为实现你想要的而应该做的事情:
客户
网络角色
工人角色
https://stackoverflow.com/questions/16703298
复制相似问题