Azure云服务 - EventProcessor IEventProcessor.ProcessEventsAsync未被点击

时间:2016-12-30 15:50:15

标签: azure azure-worker-roles azure-cloud-services azure-eventhub

我遇到了一个工作角色的问题,其中角色似乎成功启动并注册了EventProcessor类实现(EventProcessorA和EventProcessorB),但它们都没有接收任何事件。通过这个,我的意思是IEventProcessor.ProcessEventsAsync方法根本没有被击中。

每个EventProcessor类都为它设置了自己的事件中心。

我的日志显示为EventProcessor类调用构造函数和OpenAsync方法。实际上,他们被称为4次,如下所示。但在此之后,没有其他活动发生。我猜4次是因为有四个分区。

SimpleEventProcessorA - Constructor
SimpleEventProcessorA - OpenAsync
SimpleEventProcessorA - Constructor
SimpleEventProcessorA - OpenAsync
SimpleEventProcessorA - Constructor
SimpleEventProcessorA - OpenAsync
SimpleEventProcessorB - Constructor
SimpleEventProcessorB - Open Async
SimpleEventProcessorB - Constructor
SimpleEventProcessorB - OpenAsync
SimpleEventProcessorB - Constructor
SimpleEventProcessorB - OpenAsync
SimpleEventProcessorB - Constructor
SimpleEventProcessorB - OpenAsync
SimpleEventProcessorA - Constructor
SimpleEventProcessorA - OpenAsync

在Worker角色的RunAsync方法中没有为EventProcessorOptions提供偏移,因此所有事件都应该充斥着。

此外,在Azure门户网站中,我看到当我启动时会发生的事件。

注册EventProcessor的工作者角色代码:

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

    private EventProcessorHost eventProcessorHostA;
    private EventProcessorHost eventProcessorHostB;

    public override void Run()
    {
        Trace.TraceInformation("ReportWorkerRole is running");

        try
        {
            this.RunAsync(this.cancellationTokenSource.Token).Wait();
        }
        finally
        {
            this.runCompleteEvent.Set();
        }
    }

    public override bool OnStart()
    {
        // Set the maximum number of concurrent connections
        ServicePointManager.DefaultConnectionLimit = 12;

        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

        bool result = base.OnStart();

        Trace.TraceInformation("ReportWorkerRole has been started");

        //EventHub Processing
        try
        {
            string eventHubNameA = CloudConfigurationManager.GetSetting("EventHubNameA");
            string eventHubNameB = CloudConfigurationManager.GetSetting("EventHubNameB");
            string eventHubConnectionString = CloudConfigurationManager.GetSetting("EventHubConnectionString");

            string storageAccountName = CloudConfigurationManager.GetSetting("AzureStorageAccount");
            string storageAccountKey = CloudConfigurationManager.GetSetting("AzureStorageAccountKey");
            string storageConnectionString = CloudConfigurationManager.GetSetting("AzureStorageAccountConnectionString");

            string eventProcessorHostNameA = Guid.NewGuid().ToString();
            eventProcessorHostA = new EventProcessorHost(eventProcessorHostNameA, eventHubNameA, EventHubConsumerGroup.DefaultGroupName, eventHubConnectionString, storageConnectionString);

            string eventProcessorHostNameB = Guid.NewGuid().ToString();
            eventProcessorHostB = new EventProcessorHost(eventProcessorHostNameB, eventHubNameB, EventHubConsumerGroup.DefaultGroupName, eventHubConnectionString, storageConnectionString);

        }
        catch (Exception ex)
        {
            //Logging omitted
        }

        return result;
    }

    public override void OnStop()
    {
        Trace.TraceInformation("ReportWorkerRole is stopping");

        this.eventProcessorHostA.UnregisterEventProcessorAsync().Wait();
        this.eventProcessorHostB.UnregisterEventProcessorAsync().Wait();

        this.cancellationTokenSource.Cancel();
        this.runCompleteEvent.WaitOne();

        base.OnStop();

        Trace.TraceInformation("ReportWorkerRole has stopped");
    }

    private async Task RunAsync(CancellationToken cancellationToken)
    {

        var options = new EventProcessorOptions()
        {
            MaxBatchSize = 100,
            PrefetchCount = 10,
            ReceiveTimeOut = TimeSpan.FromSeconds(20),
            //InitialOffsetProvider = (partitionId) => DateTime.Now
        };

        options.ExceptionReceived += (sender, e) =>
        {
            //Logging omitted
        };

        //Tried both using await and wait
        eventProcessorHostA.RegisterEventProcessorAsync<SimpleEventProcessorA>(options).Wait();
        eventProcessorHostB.RegisterEventProcessorAsync<SimpleEventProcessorB>(options).Wait();
        //await eventProcessorHostA.RegisterEventProcessorAsync<SimpleEventProcessorA>(options);
        //await eventProcessorHostB.RegisterEventProcessorAsync<SimpleEventProcessorB>(options);

        // TODO: Replace the following with your own logic.
        while (!cancellationToken.IsCancellationRequested)
        {
            Trace.TraceInformation("Working");
            await Task.Delay(1000);
        }
    }
}

事件处理器A(与B相同的配置):

class SimpleEventProcessorA : IEventProcessor
{

    Stopwatch checkpointStopWatch;

    //Non-relevant variables omitted

    public SimpleEventProcessorA()
    {
        try
        {
            //Initializing variables using CloudConfigurationManager

            //Logging omitted
        }
        catch (Exception ex)
        {
            //Logging omitted
        }
    }

    async Task IEventProcessor.CloseAsync(PartitionContext context, CloseReason reason)
    {
        //Logging omitted

        Console.WriteLine("Processor Shutting Down. Partition '{0}', Reason: '{1}'.", context.Lease.PartitionId, reason);
        if (reason == CloseReason.Shutdown)
        {
            await context.CheckpointAsync();
        }
    }

    Task IEventProcessor.OpenAsync(PartitionContext context)
    {
        try
        {
            //Logging omitted

            Console.WriteLine("Initialized.  Partition: '{0}', Offset: '{1}'", context.Lease.PartitionId, context.Lease.Offset);
            this.checkpointStopWatch = new Stopwatch();
            this.checkpointStopWatch.Start();

            return Task.FromResult<object>(null);
        }
        catch (Exception ex)
        {
            //Logging omitted 

            return Task.FromResult<object>(null);
        }
    }

    async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable<EventData> messages)
    {
        //Logging omitted

        foreach (EventData eventData in messages)
        {
            try
            {
                //Logging omitted 

                Console.WriteLine(string.Format("Message received.  Partition: '{0}', Data: '{1}'",
                    context.Lease.PartitionId, data));
            }
            catch (Exception ex)
            {
                //Logging omitted

                throw;
            }
        }

        //Call checkpoint every 5 minutes, so that worker can resume processing from 5 minutes back if it restarts.
        if (this.checkpointStopWatch.Elapsed > TimeSpan.FromMinutes(5))
        {
            await context.CheckpointAsync();
            this.checkpointStopWatch.Restart();
        }
    }

}

感谢任何帮助,谢谢!

更新

看起来一切都很好......这是我将东西推入事件中心时使用的连接字符串。

这是我的事件中心连接字符串:

Endpoint=sb://[myEventHubName].servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;entityPath=[old-eventhub-name];SharedAccessKey=[mykey]

entityPath设置不正确。它使用的是我设置的旧事件中心名称。它应该是为eventHubNameA或eventHubNameB设置的值。

1 个答案:

答案 0 :(得分:0)

回答问题,以便其他人可以从中受益。虽然答案详见“更新”部分的问题,但我将在此重申:

entityPath设置不正确。它使用的是我设置的旧事件中心名称。它应该是为eventHubNameA或eventHubNameB设置的值。

而不是 Endpoint=sb://[myEventHubName].servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;entityPath=[old-eventhub-name];SharedAccessKey=[mykey]

应该是Endpoint=sb://[myEventHubName].servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;entityPath=[eventHubNameA];SharedAccessKey=[mykey]