簡體   English   中英

Azure Service Bus偵聽器打開了太多的TCP連接(耗盡)

[英]Azure Service Bus Listener opening too many TCP connections (exhaustion)

我們在App Services中有幾個作為連續Azure Webjob運行的Service Bus偵聽器。 總而言之,在同一S1 App Service計划上運行着12個listener-webjobs。 環境很小,每天總計大約有1000-10000條消息。 最近,我們部署了一個新的偵聽器(一個偵聽器,該偵聽器會定期將DLQ消息重新發送至原始主題長達24小時和10次重試(指數退避)),而昨天,我們在托管的App Service上收到了TCP / IP耗盡錯誤消息。 在S1上,這意味着webjobs總共打開了超過2000個TCP連接。
總而言之,我們無法解釋為什么偵聽器如此渴望TCP連接。 每個人在其應用程序生命周期中都使用一個Topic- / QueueReceiver,還使用一個單例HttpClient連接到目標API。 從理論上講,這應該意味着每個偵聽器永遠不會保持打開的TCP連接超過10個。

我分析了代碼,但沒有發現高TCP連接需求的原因。

所有偵聽器都這樣粗暴地工作(.NET控制台應用程序,在App Services中作為連續的Azure Webjob托管):

public static async Task Main(string[] args)
{
    var configuration = GetConfiguration();

    // Setup dependencies (e.g. Singleton HttpClient)
    IServiceCollection serviceCollection = new ServiceCollection();
    ConfigureServices(serviceCollection, configuration);

    IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
    var factory = serviceProvider.GetService<TopicReceiverFactory<Model>>();
    var receiver = await factory.CreateAsync();
    receiver.ReceiveMessages();

    Console.ReadLine();
}

// ctor of the receiver used above
public QueueReceiver(QueueConfiguration configuration, IHandler<T> handler, ILogger<IReceiver> logger)
        : base(logger, handler)
{
    this.configuration = configuration;

    this.Client = new QueueClient(
    this.configuration.ConnectionString,
    this.configuration.QueueName,
    this.configuration.ReceiveMode);
}

// The ReceiveMessages Method used in Main
public void ReceiveMessages()
{
    var messageHandlerOptions = new MessageHandlerOptions(this.HandleExceptionReceivedAsync)
    {
        MaxConcurrentCalls = this.configuration.MaxConcurrentCalls,
        AutoComplete = false
    };

    this.Register(messageHandlerOptions);
}

protected void Register(MessageHandlerOptions messageHandlerOptions)
{
    if (messageHandlerOptions == null)
    {
        throw new ArgumentNullException(nameof(messageHandlerOptions));
    }

    this.Client.RegisterMessageHandler(this.ProcessMessageAsync, messageHandlerOptions);
}

ProcessMessage大致具有以下邏輯:如果成功,則調用特定實體的處理程序(將消息發布到api):完成消息; 如果由於關鍵異常而失敗(例如,由於消息格式錯誤,則為JsonSerializerException),則直接使用死信。 次要異常會導致內置重試(最多十次)。

預計TCP連接永遠不會耗盡。 環境中沒有很多事情發生。

編輯:我發現從偵聽器到服務總線的出站連接是問題的根源。 App Service的“ TCP連接”分析器顯示以下信息: 出站TCP連接

我們找到了問題的根源。 請考慮以下架構:具有多個主題和一個隊列的Servicebus命名空間。 消息將發送到Service Bus偵聽器正在接收和處理消息的主題。 如果無法處理消息,則將它們轉發到中央錯誤處理隊列。 在此隊列上,一個偵聽器正在接收消息,並讀取該消息的DeadLetterSource-Property。 在此屬性中,包含有關原始主題的信息。

現在是問題所在 :當前,我們為每個消息創建一個TopicClient。 發生這種情況是因為該偵聽器不需要事先知道存在哪些主題,從而降低了可重用性。 但是,正如我們現在發現的那樣,這是不可持續的,因為您耗盡了TCP連接。

解決方案 :我們通過配置引入主題名稱,以便此偵聽器可以為整個應用程序生活方式的每個主題創建一個TopicClient。 本質上,有n個Singleton TopicClient實例同時運行。

暫無
暫無

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

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