簡體   English   中英

Azure 事件中心:QuotaExceededException:4999 個句柄限制

[英]Azure Event Hubs : QuotaExceededException : 4999 handles limit

我在 WebApi 應用程序中為 C# 使用 Azure 事件中心庫。 我在發送消息時遇到了這個異常:

"Message":"An error has occurred.",
"ExceptionMessage":"Cannot allocate more handles to the current session or connection. The maximum number of handles allowed is 4999. Please free up resources and try again., referenceId: d975f39c71a14ae5915c9adca322e110_G15"
"ExceptionType":"Microsoft.ServiceBus.Messaging.QuotaExceededException"

我認為實例化EventHubProducerClient一次並重用它而不是在每次發送消息時創建它的實例(使用IAsyncDisposable模式)將有所幫助,如EventHub Exception:Cannot allocate more handles to the current session or connection 但事實並非如此。

我相信可能會有一些更全球化的問題。 可能遺漏了什么。

  • 我正在使用具有 7 個消費者組的單個事件中心,每個消費者組都由單獨的 web 應用程序(單個)使用; 實際上還有額外的消費者組($Default),但它沒有被使用;
  • 我使用EventProcessorClient接收消息;
  • 我使用Azure.Messaging.EventHubs 5.2.0 和Azure.Messaging.EventHubs.Processor 5.2.0 包;
  • 這是整個代碼(根據快速入門完成所有操作):
    public class EventHubService : SubscriberBase
    {
        private readonly Action<string> errorHandler;
        private readonly BlobContainerClient blobContainerClient;
        private readonly EventProcessorClient eventProcessorClient;
        private readonly EventHubProducerClient eventHubProducerClient;
        private readonly int eventsToCheckpoint;
        private readonly Timer checkpointTimer;
        private int eventsSinceLastCheckpoint;
        private bool shouldUpdateCheckpoint;

        public EventHubService(EventHubSettings settings, Action<string> errorHandler) : base()
        {
            this.errorHandler = errorHandler;
            eventHubProducerClient = new EventHubProducerClient(settings.ConnectionString, settings.EventHubName);

            if (!String.IsNullOrWhiteSpace(settings.GroupId))
            {
                eventManager = new EventManager();

                blobContainerClient = new BlobContainerClient(settings.StorageConnectionString, settings.BlobContainerName);
                eventProcessorClient = new EventProcessorClient(blobContainerClient, settings.GroupId, settings.ConnectionString, settings.EventHubName);

                eventsToCheckpoint = settings.EventsToUpdateCheckpoint;
                checkpointTimer = new Timer(settings.IntervalToUpdateCheckpoint.TotalMilliseconds);
                checkpointTimer.Elapsed += (sender, eventArgs) => shouldUpdateCheckpoint = true;
            }
        }

        public override void Start()
        {
            eventProcessorClient.ProcessErrorAsync += HandleError;
            eventProcessorClient.ProcessEventAsync += ProcessEventData;
            eventProcessorClient.StartProcessingAsync().Wait();
            checkpointTimer.Start();
        }

        public override async Task Stop()
        {
            try
            {
                checkpointTimer.Stop();
                await eventProcessorClient.StopProcessingAsync();
            }
            finally
            {
                eventProcessorClient.ProcessEventAsync -= ProcessEventData;
                eventProcessorClient.ProcessErrorAsync -= HandleError;
            }
        }

        public override async Task Publish(string topic, JObject message)
        {
            using (EventDataBatch eventBatch = await eventHubProducerClient.CreateBatchAsync())
            {
                var @event = new Event(topic, message);
                string json = @event.ToString(Formatting.None);
                byte[] bytes = Encoding.UTF8.GetBytes(json);
                var eventData = new EventData(bytes);
                eventBatch.TryAdd(eventData);

                await eventHubProducerClient.SendAsync(eventBatch);
            }
        }

        private async Task ProcessEventData(ProcessEventArgs eventArgs)
        {
            if (eventArgs.CancellationToken.IsCancellationRequested)
            {
                return;
            }

            if (++eventsSinceLastCheckpoint >= eventsToCheckpoint)
            {
                eventsSinceLastCheckpoint = 0;
                shouldUpdateCheckpoint = true;
            }

            if (shouldUpdateCheckpoint)
            {
                await eventArgs.UpdateCheckpointAsync();
                shouldUpdateCheckpoint = false;
            }

            string json = Encoding.UTF8.GetString(eventArgs.Data.Body.ToArray());
            var @event = new Event(json);
            eventManager.TryRaise(@event);
        }

        private Task HandleError(ProcessErrorEventArgs eventArgs)
        {
            if (!eventArgs.CancellationToken.IsCancellationRequested)
            {
                errorHandler.Invoke($"[P:{eventArgs.PartitionId}][O:{eventArgs.Operation}] {eventArgs.Exception.Message}");
            }

            return Task.CompletedTask;
        }
    }  

我在服務總線配額中找到了一些信息,例如:

隊列、主題或訂閱實體 (5000) 上的並發接收請求數。

隨后的接收請求被拒絕,並且調用代碼接收到異常。 此配額適用於一個主題的所有訂閱的並發接收操作的總和。

但仍然不知道如何處理它。

請幫忙。 謝謝。

這確實是EventHub 異常的答案:無法為當前會話或連接分配更多句柄

我為NET Core 的Azure 事件中心庫做了類似的“修復”,但我忘記了我也在使用NET 框架的Azure 事件中心庫!

所以我已經實例化了EventHubProducerClient一次並現在重用它。 似乎工作正常。

我的錯。 不夠細心。

在我的例子中,除了只創建一個 Client 實例外,只使用一個 sender 實例。 我每次發送消息時都使用方法CreateSender,它也會產生異常

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM