如何并行化azure worker角色?
我在azure中运行了一个工作者角色 此工作进程处理包含大量整数的队列。对于每个整数,我必须进行相当长的处理(根据整数,从1秒到10分钟) 由于这相当耗时,我希望并行处理这些过程。不幸的是,当我使用400个整数的队列进行测试时,我的并行化似乎没有效率 以下是我的实现:如何并行化azure worker角色?,azure,azure-worker-roles,parallel.foreach,Azure,Azure Worker Roles,Parallel.foreach,我在azure中运行了一个工作者角色 此工作进程处理包含大量整数的队列。对于每个整数,我必须进行相当长的处理(根据整数,从1秒到10分钟) 由于这相当耗时,我希望并行处理这些过程。不幸的是,当我使用400个整数的队列进行测试时,我的并行化似乎没有效率 以下是我的实现: public class WorkerRole : RoleEntryPoint { private readonly CancellationTokenSource cancellationTokenSour
public class WorkerRole : RoleEntryPoint {
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false);
private readonly Manager _manager = Manager.Instance;
private static readonly LogManager logger = LogManager.Instance;
public override void Run() {
logger.Info("Worker is running");
try {
this.RunAsync(this.cancellationTokenSource.Token).Wait();
}
catch (Exception e) {
logger.Error(e, 0, "Error Run Worker: " + e);
}
finally {
this.runCompleteEvent.Set();
}
}
public override bool OnStart() {
bool result = base.OnStart();
logger.Info("Worker has been started");
return result;
}
public override void OnStop() {
logger.Info("Worker is stopping");
this.cancellationTokenSource.Cancel();
this.runCompleteEvent.WaitOne();
base.OnStop();
logger.Info("Worker has stopped");
}
private async Task RunAsync(CancellationToken cancellationToken) {
while (!cancellationToken.IsCancellationRequested) {
try {
_manager.ProcessQueue();
}
catch (Exception e) {
logger.Error(e, 0, "Error RunAsync Worker: " + e);
}
}
await Task.Delay(1000, cancellationToken);
}
}
}
以及ProcessQueue的实现:
public void ProcessQueue() {
try {
_queue.FetchAttributes();
int? cachedMessageCount = _queue.ApproximateMessageCount;
if (cachedMessageCount != null && cachedMessageCount > 0) {
var listEntries = new List<CloudQueueMessage>();
listEntries.AddRange(_queue.GetMessages(MAX_ENTRIES));
Parallel.ForEach(listEntries, ProcessEntry);
}
}
catch (Exception e) {
logger.Error(e, 0, "Error ProcessQueue: " + e);
}
}
在ProcessQueue函数中,我尝试使用不同的MAX_条目值:首先=20,然后=2。
当MAX_ENTRIES=20时,速度似乎较慢,但无论MAX_ENTRIES的值是多少,速度似乎相当缓慢
我的虚拟机是A2媒体
我真的不知道我是否正确地进行了并行化;也许问题来自于工人本身(这可能是很难并行的)。
这里要考虑的一些事情:
- 代码将等待所有已启动的线程完成处理后再继续。因此,如果您有5个线程,每个线程需要10秒,1个线程需要10分钟,那么Parallel.Foreach的总处理时间将是10分钟
- 即使假设所有线程都将同时开始处理,Parallel.Foreach也不会以这种方式工作。它查看服务器上的内核数和其他参数,通常只启动它认为可以处理的线程数,而不知道这些线程中有什么。因此,如果您有很多非CPU绑定的线程,它们/可以/可以/同时启动,而不会导致CPU过度利用,那么默认行为可能不会以最佳方式运行它们
希望这有帮助并且有意义您没有提到您正在使用哪种Azure消息队列技术,但是对于我希望并行处理多条消息的任务,我倾向于在服务总线队列和订阅上使用消息泵模式,利用OnMessage()方法在服务总线队列和订阅客户端上都可用:
- QueueClient OnMessage()
- SubscriptionClient OnMessage()-
- 这些东西的工作原理概述:-)-
public override void Run()
{
var onMessageOptions = new OnMessageOptions()
{
AutoComplete = true, // Message-Pump will call Complete on messages after the callback has completed processing.
MaxConcurrentCalls = 2 // Max number of threads the Message-Pump can spawn to process messages.
};
sbQueueClient.OnMessage((brokeredMessage) =>
{
// Process the Brokered Message Instance here
}, onMessageOptions);
RunAsync(_cancellationTokenSource.Token).Wait();
}
如果需要,您仍然可以利用RunAsync()方法在主辅助角色线程上执行其他任务
最后,我还建议您考虑将Worker角色实例扩展到至少2个(用于容错和冗余),以提高总体吞吐量。从我在该模式的多个生产部署中看到的情况来看,当多个工作者角色实例运行时,OnMessage()的性能非常好。谢谢您的回答。我的工人使用了99.9%的CPU;所以我可能还有另一个问题?为什么不使用多个A1实例呢?谢谢你的回答。我不明白。有两个A1而不是一个A2更好吗?无论如何,SLA至少要覆盖两个实例。每个可以是A1,一次只处理一个项目。这可以简化很多事情。
public override void Run()
{
var onMessageOptions = new OnMessageOptions()
{
AutoComplete = true, // Message-Pump will call Complete on messages after the callback has completed processing.
MaxConcurrentCalls = 2 // Max number of threads the Message-Pump can spawn to process messages.
};
sbQueueClient.OnMessage((brokeredMessage) =>
{
// Process the Brokered Message Instance here
}, onMessageOptions);
RunAsync(_cancellationTokenSource.Token).Wait();
}