高CPU Azure工作者角色

时间:2017-09-22 08:37:57

标签: c# multithreading azure azure-worker-roles azure-iot-hub

所以这是一个相当广泛的问题,但已经没有想法了。 我们当前正在运行2个工作者角色实例,它们执行以下操作:

  • 通过为每个批次生成N个线程来监视和处理IoT Hub事件。
  • 监视和处理来自IoT Hub的连接/断开(操作监视)消息
  • 某些服务总线是否正常工作(主题和队列)
  • 写入SQL,DocDB(Mongo API)和Azure表存储以通过NLOG进行日志记录
  • 通过IoT Hub发送云到设备消息

我们面临的问题是在高峰期间我们的CPU显然会增加,但遗憾的是它永远不会降低,并且通常会高达100%并且坐在那里直到我重新启动实例以使其恢复原状。我一直在研究线程,因为我仍然觉得它可能与一个"而(1)"类型场景,即使不知道为什么。让我们现在进入代码......

WorkerRole.cs

    class WorkerRole : RoleEntryPoint
    {
        private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false);

        public override void Run()
        {
            _eventprocessor.Start(instanceId, instanceIndex);//.Wait(-1);

            //Wait for shutdown to be called, else the role will recycle
            this.runCompleteEvent.WaitOne();
        }
    }

EventProcessor.cs 中: 我会尝试省去很多果汁但添加我觉得可能值得的东西。将添加"伪代码"在可能的情况下。

public class EventProcessor : IEventProcessor
{
  private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false);

  public async Task Start(string serviceId, int InstanceIndex)
  {

    //Setup Topic

    //Setup Queue

    //Setup EventProcessorHost for receiving events and operations monitoring and start listening

    //Receiving cloud to device feedback from service
    ReceiveFeedbackAsync();

    runCompleteEvent.WaitOne();
  }

  async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
  {
        if (messages.Count() > 0)
        {
            if (!_cancellationSource.IsCancellationRequested)
            {
                await ProcessEventsBulk(context, messages);
            }
        }

        if (messages.Count() > 0)
        {
            await context.CheckpointAsync();               
        }
   }

  async Task ProcessEventsBulk(PartitionContext context, IEnumerable<EventData> messages)
        {
            List<Task> TaskList = new List<Task>();
            foreach (EventData message in messages)
            {
                var LastTask = Task.Run(() => GoBoy(context, message));
                TaskList.Add(LastTask);
            }
            await Task.WhenAll(TaskList);
        }

    async Task GoBoy(PartitionContext context, EventData message)
    {
        try
        {
            using (var db = new AppDbContext(_dbContextConnectionString))
            {
                await ProcessEvent(message, context.Lease.PartitionId, new CoreManagerContainer(db), db);
                await db.SaveChangesAsync();
            }
        }
        catch (Exception e)
        {
           //Do Some stuff...
        }
    }

  private async void ReceiveFeedbackAsync()
    {
        var feedbackReceiver = serviceClientReceiver.GetFeedbackReceiver();
        while (true)
        {
            try
            {
              var feedbackBatch = await feedbackReceiver.ReceiveAsync();
              if (feedbackBatch == null) continue;
              foreach (var records in feedbackBatch.Records)
              {

              }
              await feedbackReceiver.CompleteAsync(feedbackBatch);
            }
            catch (Exception)
            {
              Thread.Sleep(30000);                    
            }
         }

    }

}

如果有任何人需要,请不要犹豫。我非常感谢任何帮助。

此处显示重新启动工作人员后的CPU丢失 enter image description here

微软支持协助我要求我做一些PerfViews和一些ProcDumps。结果是我们应该调查调用我们的中心的线程&#34; https://abcxyz.azure-devices.net:443/ $ iothub / websocket&#34;。这就是为什么我决定添加ReceiveFeedbackAsync()方法,因为我知道它依赖于永久连接到我们的集线器来收集反馈。

从我可以看到,我们正在正确注册我们的EVPH,但是如果有人想查看该代码,请告诉我。

1 个答案:

答案 0 :(得分:0)

您已逐步执行代码,并确保未创建没有引发任何异常的无限循环条件,以便执行Thead.Sleep。由于您期望代码休眠,因此最好避免使用Exception来触发它。也许在处理每一批反馈后将其编码为睡眠。异常适用于错误处理和特殊情况,而不有助于控制逻辑流程。