You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure WebPubSub发送消息引发内存泄漏问题求助

WebPubSub发送消息导致内存增长的问题分析与解决方案

问题概述

Web App运行一段时间后因内存不足重启,排查发现使用Azure WebPubSub发送消息后内存持续增长。并发发送100条消息时,HttpConnectionPool会创建100个连接导致非托管内存骤增;后续发送虽复用连接,但堆内存仍有大量分配,仅调用GC.Collect()能临时缓解。

关键问题解答

1. HttpConnectionPool连接存活时长

Azure WebPubSub SDK底层依赖HttpClient的连接池,默认配置下:

  • 空闲连接的存活时长为2分钟(对应ServicePointManager.DefaultConnectionLeaseTimeout,或Azure Core中HttpClientOptions.ConnectionLeaseTimeout)。
  • 并发请求时,连接池会根据请求数量创建新连接,直到达到MaxConnectionsPerServer上限(默认无硬限制,实际受系统资源约束)。空闲连接超过存活时长后,会被自动回收释放。

2. 堆内存存储的数据及释放方式

堆内存主要分配以下对象:

  • 请求/响应的RequestContent实例及序列化后的消息内容
  • Azure SDK的请求上下文对象(如OperationContext、请求追踪数据)
  • HttpClient的请求消息、响应消息实例
  • 异常对象(若请求失败产生RequestFailedException)

这些均为托管对象,默认由.NET GC自动回收。但高并发场景下,短生命周期对象会快速积累,直到GC触发Gen0/Gen1回收。若存在未释放的引用(如未完成的Task、未取消的事件注册),会导致对象无法被回收,形成内存泄漏。

3. 根本解决方案

(1)全局复用WebPubSubServiceClient

WebPubSubServiceClient是线程安全的,应作为全局单例使用,避免每次请求创建新实例。每个client实例自带独立的HttpClient连接池,复用能有效共享连接,减少连接创建开销。

(2)自定义连接池配置

通过WebPubSubClientOptions配置HttpClient参数,限制并发连接数、缩短空闲连接存活时间:

using Azure.Core;
using Azure.Messaging.WebPubSub;
using System.Net.Http;

var connectionString = "<ConnectionString>";
var hub = "<HubName>";

var clientOptions = new WebPubSubClientOptions();
clientOptions.HttpClient = new HttpClient(new HttpClientHandler
{
    MaxConnectionsPerServer = 20, // 限制单服务器并发连接数
    ConnectionLeaseTimeout = 30 * 1000 // 空闲连接30秒后回收
});

// 全局单例的client
var serviceClient = new WebPubSubServiceClient(connectionString, hub, clientOptions);

(3)优化请求内容的生命周期

用using包裹RequestContent,确保对象及时释放,减少堆内存占用:

Task[] tasks = new Task[100];
for (int i = 0; i < 100; i++)
{
    using var content = RequestContent.Create("Message");
    tasks[i] = serviceClient.SendToUserAsync("testUser", content, ContentType.TextPlain);
}
Task.WaitAll(tasks);

(4)批量发送消息

使用批量接口减少请求数量,降低连接池压力:

// 批量发送给多个用户
var userIds = new List<string> { "testUser1", "testUser2", ... };
await serviceClient.SendToUsersAsync(userIds, RequestContent.Create("Batch Message"), ContentType.TextPlain);

(5)升级Azure SDK版本

确保使用最新版的Azure.Messaging.WebPubSub NuGet包,旧版本可能存在已知的内存泄漏bug,升级可修复此类问题。

(6)避免强制调用GC.Collect()

强制GC会打断正常的垃圾回收节奏,影响应用性能。优化对象生命周期和连接池配置后,依赖.NET自动GC即可有效回收内存。

内容的提问来源于stack exchange,提问作者Oleksandr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:45:42