我有以下设置:部署了 N 个 Azure Worker Role 实例。我们的桌面应用程序将一条消息上传到 Azure,然后上传一组与该消息相关的图像。Message 知道它需要什么图像。
这 2 个活动(消息上传和图像上传)是独立的- 图像甚至可以在用户生成消息之前上传(称为缓存 - 但它更复杂),或者在消息上传到 Azure 之后几秒/分钟。
我将消息存储在 Azure MSSQL 数据库中,图像存储在 blob 中,它们的 URL 存储在数据库中。还有一个MessageToImage表,它存储指向消息图像的链接。这是一个简化的数据库结构(请原谅我的 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 个消息的图像 - 哪个实例将“选择”它应该将消息发送到进一步处理?我怎么能保证它只会发生一次?
到目前为止,我提出了以下想法:
确保“为图像更新 BlobUrl”数据库逻辑将是原子的,并将返回消息的“丢失”图像的数量。这样,我将仅在一个实例上触发进一步处理 - 作为数据库更新结果接收“0”的实例。但是:我怎样才能在 MSSQL 级别上做到这一点?更复杂 - 我如何使用实体框架来做到这一点?
有一个专门的工作人员角色,该工作将选择具有所有图像的消息 - 并将它们发送以进行处理。但这不能很好地扩展......而且看起来有点难看。
还有其他想法/建议吗?
谢谢!
UPDATE1 @Richard 和 @Rob 建议使用服务总线队列。我确实调查过了。我仍然没有答案的部分是 WORKER ROLE 中决定何时将消息发送到队列进行处理的代码应该是什么样子?仅当数据库/blob 中存在所有图像(即上传到 Azure 云)时,才会将消息发送到队列。在这里,我仍然想指出我的极端案例——我有 10 个图像同时由 10 个工作角色处理。对于所有实例,处理同时结束。每个角色都使用上传的图像 URL 更新数据库。然后我应该以某种方式触发最终的消息处理——这意味着其中一个实例应该获得优先级。而且我不清楚我应该如何做到这一点。
希望这使我的问题更清晰。