崩溃后从同一位置启动线程

本文关键字:位置 启动 线程 崩溃 | 更新日期: 2023-09-27 18:30:26

我正在为 Windows Azure 编写一个 Worker Role。工作线程从队列接收消息,对于每条消息,它都会启动一个线程。线程正在调用外部 API,这涉及大量线程等待:即我可以调用"创建实例",API 将返回202 Accepted,然后我将不得不轮询 API 以获取"已完成"答案。有时等待可能是 5 分钟。整个过程可能需要 10 到 30 分钟,大约需要 10 次调用 API。

Azure 辅助角色的生命周期中有 30 分钟很长,在此期间可能会发生重启/重新部署/崩溃。而且我的流程不是幂等的,我无法毫无问题地创建两次相同的资源。

我想做的是在每次对 API 的关键调用中,将线程的状态存储在某个地方。因此,如果线程在某处崩溃,另一个辅助角色可以从队列中获取消息,并从前一个进程中断的同一进程点起飞。

其中一个想法是报告线程状态并将其保留在某个地方。像这样的伪代码:

pubilc class WorkerRole{
    public override Run(){
        while(true)
        {
            var message = Queue.GetMessage();
            var messageProcessor = new MessageProcessor(message);
            var thread = new Thread();
            thread.Run(messageProcessor.Process());
            Thread.Sleep(1 minute);
        }   
    }
}

public class MessageProcessor
{
    private QueueMessage message;
    public MessageProcessor(QueueMessage message){
        this.message = message 
    }
    public void Process()
    {
        if(!ThreadReporter.IsComplete(message, "Step1")
        {
            ExtenalApi.StartStep1();
        }
        ThreadReporter.ReportCompletion(message, "Step1");
        if(!ThreadReporter.IsComplete(message, "Step2"))
        {
            ExternalApi.StartStep2();
        }
        ThreadReporter.ReportCompletion(message, "Step2");
    }
}

ThreadReporter会在数据库中的某个地方保存一个标志,表明 Step1 已完成,或者会检查是否已为该特定消息(工作请求)设置了 Step1 的标志。

我能感觉到这种方法会有很多问题,代码会很糟糕。但我很难想出更好的方法来做到这一点。

我见过Jon Skeet正在保存应用程序的某种MemoryDump,并在重新启动后从同一位置起飞。是否可以序列化线程状态以保存在数据库中?

我也听说工作流基金会也可以做到这一点。我从未与 WF 合作过,对此一无所知。关于 WF 的任何提示?

所以,问题是,实现崩溃后可以从最后一个点开始的工作流(本质上是一个工作流)的最佳方法是什么?

崩溃后从同一位置启动线程

这正是长时间运行的持久化工作流旨在解决的问题。

正如您所说,线程运行和暂停(大概是循环线程睡眠)并不理想。

可能是时候重新架构了。您关于在数据库的每个步骤后保持当前播放状态的建议可以正常工作,但如果您有带宽,我肯定会研究长时间运行的工作流程。

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