C# 类似队列的WebJob上的Azure WorkerRole触发器
我习惯于在Azure上使用webjob触发Azure队列。它就像一个符咒 queueTrigger的真正好处是,在消息触发的进程未完成之前,消息保持不可见(而不是删除)。因此,如果您关闭webjob(例如,对于webjob更新),消息将在队列中可见(在一点超时后),以便由更新的webjob(完美)处理 现在我想做同样的事情,但在一个工人的角色。今天我真的很喜欢这个C# 类似队列的WebJob上的Azure WorkerRole触发器,c#,azure,azure-worker-roles,azure-webjobs,azure-queues,C#,Azure,Azure Worker Roles,Azure Webjobs,Azure Queues,我习惯于在Azure上使用webjob触发Azure队列。它就像一个符咒 queueTrigger的真正好处是,在消息触发的进程未完成之前,消息保持不可见(而不是删除)。因此,如果您关闭webjob(例如,对于webjob更新),消息将在队列中可见(在一点超时后),以便由更新的webjob(完美)处理 现在我想做同样的事情,但在一个工人的角色。今天我真的很喜欢这个 while (true) { var cloudMessage = await sourceImportationQue
while (true)
{
var cloudMessage = await sourceImportationQueue.GetMessageAsync();
if (cloudMessage != null)
sourceImportationQueue.DeleteMessage(cloudMessage);
// process my job (few hours)
else
await Task.Delay(1000 * 5);
}
但是,如果我在工作期间阻止工人,我就会丢失信息。那么我如何才能像webJob一样触发呢?默认情况下,一旦检索到队列消息,它将在5分钟内不可见。在此延迟之后,如果消息尚未从队列中删除,它将再次可见,以便可以再次对其进行处理
在代码示例中,您将在从队列中获取消息后立即删除该消息。如果您想确保安全,则只应在流程结束时删除邮件。您是否尝试移动
SourceImportionQueue.DeleteMessage(cloudMessage)代码>在处理作业结束时?如果不使用某种持久性存储来跟踪作业进度,可能无法解决此问题。如前所述,您正在作业开始前删除消息,因此如果作业因任何原因(包括停止角色)失败,消息将丢失。消息的最长锁定时间为5分钟,这意味着当作业仍在运行时,消息将再次出现,如果删除操作移到末尾,则会因丢失锁定而失败
如果长时间运行的作业由多个较小的步骤组成,其中没有一个步骤超过5分钟,则可以定期调用RenewLock(),以保留消息上的锁,并阻止消息重新出现在队列中。在这种情况下,只要锁永不过期,最后的DeleteMessage就会成功。不过,这不太可能符合您的情况
一个可能的解决方案是在整个作业处理过程中将作业状态写入Azure表和记录状态。您的工作者角色循环将检查表中是否有任何尚未完成的作业,并继续任何存在的作业,如果没有找到,则检查服务总线中是否有任何新作业。此解决方案还可以让您有机会从失败的作业到达的点开始选择失败的作业,而不是从头开始2小时的作业。最后,我找到了一个简单的解决方案。在运行几个小时的作业之前,我启动了一个任务KeepHiddenMessageAsync
,用超时更新消息。在超时结束之前,完成消息的新更新。如果出现问题,则消息将超时,消息将可见
private bool jobIsComplete;
private void Run()
{
while (true)
{
jobIsComplete = false;
//get the message
var cloudMessage = await queue.GetMessageAsync();
if (cloudMessage != null)
//run the task to keep the message until end of the job and worker role stopping for an update for example
var keepHiddenMessageTask = KeepHiddenMessageAsync(cloudMessage);
//
// process my job (few hours)
//
jobIsComplete = true;
await keepHiddenMessageTask;
await _queue.DeleteMessageAsync(cloudMessage);
else
await Task.Delay(1000 * 5);
}
}
private async Task KeepHiddenMessageAsync(CloudQueueMessage iCloudQueueMessage)
{
while (true)
{
//Update message and hidding during 5 new minutes
await _queue.UpdateMessageAsync(iCloudQueueMessage, TimeSpan.FromMinutes(5), MessageUpdateFields.Visibility);
//Wait 4 minutes
for (int i = 0; i < 60 * 4; i++)
{
if (JobIsComplete)
return;
else
await Task.Delay(1000);
}
}
}
private bool作业已完成;
私家车
{
while(true)
{
jobIsComplete=假;
//明白了吗
var cloudMessage=wait queue.GetMessageAsync();
if(cloudMessage!=null)
//运行任务以将消息保留到作业结束,并停止工作人员角色以进行更新(例如)
var keepHiddenMessageTask=KeepHiddenMessageAsync(cloudMessage);
//
//处理我的工作(几个小时)
//
jobIsComplete=true;
等待keepHiddenMessageTask;
wait_queue.DeleteMessageAsync(cloudMessage);
其他的
等待任务。延迟(1000*5);
}
}
专用异步任务KeepHiddenMessageAsync(CloudQueueMessage iCloudQueueMessage)
{
while(true)
{
//在新的5分钟内更新消息和隐藏
wait _queue.UpdateMessageAsync(iCloudQueueMessage,TimeSpan.FromMinutes(5),MessageUpdateFields.Visibility);
//等4分钟
对于(int i=0;i<60*4;i++)
{
如果(作业完成)
返回;
其他的
等待任务。延迟(1000);
}
}
}
我同意你的看法,但是;)正如所写的那样,这项工作需要几个小时(代码注释),因此无法在结尾处移动Deltemessage是的,我没有注意到这一点。使用QueueTrigger属性时的问题是-AFAIK-无法自定义正在处理的消息的不可见性超时。那么,在while(true)中轮询队列,然后更好地控制这个参数怎么样?谢谢你的回答,我喜欢你的nenewlock建议,但也许它可以像在webjob触发器中一样运行。但是我不知道机械是如何工作的?Azure WebJobs SDK也可以在WorkerRole中工作-因此您也可以在那里使用相同的QueueTrigger代码。
private bool jobIsComplete;
private void Run()
{
while (true)
{
jobIsComplete = false;
//get the message
var cloudMessage = await queue.GetMessageAsync();
if (cloudMessage != null)
//run the task to keep the message until end of the job and worker role stopping for an update for example
var keepHiddenMessageTask = KeepHiddenMessageAsync(cloudMessage);
//
// process my job (few hours)
//
jobIsComplete = true;
await keepHiddenMessageTask;
await _queue.DeleteMessageAsync(cloudMessage);
else
await Task.Delay(1000 * 5);
}
}
private async Task KeepHiddenMessageAsync(CloudQueueMessage iCloudQueueMessage)
{
while (true)
{
//Update message and hidding during 5 new minutes
await _queue.UpdateMessageAsync(iCloudQueueMessage, TimeSpan.FromMinutes(5), MessageUpdateFields.Visibility);
//Wait 4 minutes
for (int i = 0; i < 60 * 4; i++)
{
if (JobIsComplete)
return;
else
await Task.Delay(1000);
}
}
}