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

Azure部署的.NET Core 2.0 Web API出现TCP连接泄漏问题

排查Azure上ASP.NET Core Web API的TCP连接泄漏问题

我之前帮不少团队解决过Azure App Service里TCP连接持续增长的问题,结合你提到的技术栈(ASP.NET Core MVC、EF Core、SignalR),咱们一步步拆解排查方向,精准定位问题:

1. 先明确是哪种连接在泄漏

首先得搞清楚增长的TCP连接到底是HTTP/SignalR的客户端连接,还是EF Core的数据库连接。Azure有现成的监控可以帮你快速区分:

  • 登录Azure门户,进入你的App Service,打开「监控」->「指标」:
    • 查看TCP Connections(总TCP连接数)的趋势
    • 同时查看Http Connections(HTTP活跃连接数)和WebSocket Connections(SignalR的WebSocket连接数)
  • 如果用的是Azure SQL数据库,去对应的SQL资源里查看Active Connections指标
    对比这些指标的增长趋势,就能快速定位是哪类连接出了问题。

2. 排查SignalR WebSocket连接泄漏

SignalR的WebSocket连接很容易因为客户端异常断开、清理逻辑不到位导致残留,这是最常见的原因之一:

  • 检查Hub的断开逻辑:确保OnDisconnectedAsync方法正确实现,并且没有吞异常导致框架的默认清理流程中断:
    public override async Task OnDisconnectedAsync(Exception exception)
    {
        try
        {
            // 这里放你的业务清理逻辑,比如移除用户-连接ID的映射
            await _userConnectionManager.RemoveConnection(Context.ConnectionId);
        }
        catch (Exception ex)
        {
            // 一定要记录日志,别让异常打断后续的框架清理
            _logger.LogError(ex, "Failed to clean up connection {ConnectionId}", Context.ConnectionId);
        }
        // 必须调用基类方法,框架会处理底层WebSocket连接的释放
        await base.OnDisconnectedAsync(exception);
    }
    
  • 调整SignalR的超时配置:如果客户端网络异常断开,服务器需要及时检测到并释放连接。可以在Startup/Program.cs里调整:
    services.AddSignalR(options =>
    {
        options.KeepAliveInterval = TimeSpan.FromSeconds(10); // 主动发心跳的间隔
        options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); // 多久没收到客户端响应就判定断开
    });
    
  • 查看WebSocket连接指标:如果WebSocket Connections和总TCP连接的增长趋势完全一致,那基本可以确定是SignalR连接没正确释放。

3. 排查EF Core数据库连接泄漏

EF Core默认用连接池,但如果使用不当,也会导致连接被长期占用无法回收:

  • 检查DbContext的使用方式:绝对不要手动new MyDbContext()却不释放,也不要在using块之外持有DbContext实例。正确的做法是依赖注入(框架自动管理生命周期),或者用using包裹:
    // 推荐:依赖注入DbContext
    public class MyApiController : ControllerBase
    {
        private readonly MyDbContext _dbContext;
        public MyApiController(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }
    }
    
    // 手动创建时必须用using
    using var dbContext = new MyDbContext(_configuration.GetConnectionString("Default"));
    var data = await dbContext.MyEntities.ToListAsync();
    
  • 检查异步操作是否完整:如果异步方法没加await,会导致DbContext被长时间持有,连接池无法回收连接。比如:
    // 错误:没加await,DbContext会被一直占用
    _dbContext.MyEntities.AddAsync(new Entity());
    // 正确:必须await异步操作
    await _dbContext.MyEntities.AddAsync(new Entity());
    
  • 开启EF Core连接日志:可以在配置里开启日志,查看连接的获取和释放情况:
    services.AddDbContext<MyDbContext>(options =>
    {
        options.UseSqlServer(_configuration.GetConnectionString("Default"))
               .LogTo(message => _logger.LogInformation(message), LogLevel.Information);
    });
    

如果Azure SQL的Active Connections和总TCP连接同步增长,那重点排查EF Core的连接使用。

4. 排查ASP.NET Core HTTP连接的异常情况

虽然框架自动管理HTTP连接,但有些自定义逻辑可能会导致连接残留:

  • 检查自定义中间件/过滤器:有没有在中间件里持有HttpContext,或者未正确完成请求处理?比如操作context.Response.Body后没释放,或者异步操作卡住没完成。
  • 查看异常请求指标:在App Service的指标里查看Http 5xx Errors,如果有大量异常请求,可能会导致连接没正常关闭。
  • 调整Kestrel连接限制:可以在Program.cs里设置Kestrel的连接上限,避免无限制增长:
    builder.WebHost.ConfigureKestrel(options =>
    {
        options.Limits.MaxConcurrentConnections = 1000; // 根据你的流量调整
        options.Limits.MaxConcurrentUpgradedConnections = 500; // WebSocket升级连接的上限
    });
    

5. 用诊断工具深入分析

如果上面的排查还没找到根源,就需要用工具抓更详细的信息:

  • Azure内置诊断工具:在App Service的「诊断和解决问题」里搜索「TCP连接」,可以查看当前连接的状态、远程IP、端口,判断是哪些连接在持续增长。
  • Application Insights依赖跟踪:启用AI的依赖跟踪,查看所有出站连接(数据库、外部API)的生命周期,有没有未完成的依赖调用。
  • dotnet-counters实时监控:在本地或者Azure的SSH会话里运行dotnet-counters,实时查看Socket连接数和EF Core连接池的使用情况:
    dotnet-counters monitor --process-id <你的App Service进程ID> --counters System.Net.Sockets,Microsoft.EntityFrameworkCore
    

按照这个流程一步步排查,应该能快速定位到连接泄漏的根源。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:37:24