我目前正在尝试将处理器密集型模拟任务划分为数百个块,这些块在 Azure 中并行处理。我认为 Azure 网站提供了易于设置的专用虚拟机和 WebJobs 以及易于使用的存储队列抽象,非常符合我的要求。
我有以下 Azure 设置,每次运行时都会由我的代码全新创建
- 单个存储帐户
- 一个带有作业描述的存储队列
- 带有静态数据的存储容器
- 结果的存储容器(每个作业的唯一文件)
- n(例如 8 个)“标准”网站,表示有 n 个不同的 *.azurewebsites.net URI
- 使用 WebJobs SDK (JobHost) 在每个网站上连续运行一个 WebJob(示例中为 8 个 WebJobs)
- 每个职位描述<1k
- 每个作业包含大约 100k 的 Blob-input-data
- 每个结果大约是 100k 的 Blob-output-data
- 在当前的缩放下,每个作业运行大约一分半钟
这是工作的签名。
public static void RunGeant4Simulation(
[QueueTrigger("simulationjobs")] JobDescription jobDescription,
[Blob("input/{Archive}", FileAccess.Read)] Stream archive,
[Blob("result/{Name}-{Energy}-output.zip", FileAccess.Write)] Stream output,
[Blob("result/{Name}-{Energy}-log.dat")] TextWriter debug
)
然后代码继续设置网站本地的、特定于作业的目录,提取包含可执行文件的 zip 存档,使用 Process.Start 运行此可执行文件并将捕获的输出写入 blob。进程访问的所有内容都在机器上可用。调试 TextWriter 用于捕获作业中的计时信息。
我期望看到的是,每个网站都会从队列中获取一个作业,运行它,将结果发布到容器中并执行下一个作业。
我实际看到的是,实际上只有一个 WebSite 正在运行作业,而其余的只是空闲,尽管 WebJob 被报告为在每个站点上启动并运行。最终结果是每分钟完成的作业数量与一个网站相同。这是一个运行日志,其中两个网站“决定”参与运行作业:simulation-log.zip。连接字符串中提到的存储帐户已被删除,因此我没有从日志中删除访问密钥。
我已经为 WebJob 添加了一些计时工具,从中我可以看到有时运行可执行文件需要两倍或三倍(几乎完全准确)的时间,它会在“正常”运行中花费
stopwatch.Start();
using (var process = Process.Start(processStartInfo))
{
debug.WriteLine("After Starting Process: {0}", DateTime.UtcNow);
var outputData = process.StandardOutput.ReadToEnd();
process.WaitForExit();
stopwatch.Stop();
debug.WriteLine("Process Finished: {0} {1}", DateTime.UtcNow, stopwatch.Elapsed);
outputBytes = Encoding.UTF8.GetBytes(outputData);
}
秒表显示的时间为 1:15、2:27、3:43 等。但一些耗时比预期更长的作业也会显示秒表的预期时间。但是,在这两种情况下,都会运行另一个网站上的作业,并且会在存储的结果容器中显示结果。最后,每分钟完成的作业数量不会改变。
更新
今天,我更进一步,为每个网站创建了一个单独的存储帐户,并在 8 个存储帐户中的 8 个队列之间手动分配作业,每个队列用于 8 个网站之一。这意味着从我的外部角度来看,除了偶然运行相同的代码之外,没有任何共同点。
这没有帮助。
看起来我仍然只有一个处理器,它必须在我创建的任何网站上运行所有 WebJobs,无论它们多么独立。我创建了 CPU 时间的图像,如门户所示: