商城首页欢迎来到中国正版软件门户

您的位置:首页 >C#在Docker/K8s中高并发部署要点

C#在Docker/K8s中高并发部署要点

  发布于2026-01-01 阅读(0)

扫一扫,手机访问

ASP.NET Core 高并发部署需调优 Kestrel 连接限制、Kubernetes 探针配置、Docker 镜像精简、HttpClient 单例复用及 DNS 缓存策略,否则将引发连接拒绝、Pod 误重启、OOMKilled 和随机超时。

c# 在Docker/Kubernetes中部署c#高并发应用的注意事项

ASP.NET Core 应用必须启用 Kestrel 的并发连接限制调优

默认 Kestrel 的最大并发连接数是 1000,高并发场景下会直接触发连接拒绝(错误如 ConnectionRefused 或日志中出现 Too many open connections)。这不是 Docker 网络问题,而是 Kestrel 自身的硬限制。

  • Program.cs 中显式配置:
    var builder = WebApplication.CreateBuilder(args);
    builder.WebHost.ConfigureKestrel(serverOptions =>
    {
        serverOptions.Limits.MaxConcurrentConnections = 5000;
        serverOptions.Limits.MaxConcurrentUpgradedConnections = 5000;
    });
  • 注意 MaxConcurrentUpgradedConnections 对 WebSocket 和 HTTP/2 升级连接同样关键,不设会导致长连接堆积失败
  • 该值不能超过宿主机 ulimit -n,Docker 容器默认只有 1024,需在 docker run 或 Kubernetes securityContext 中同步提升:
    securityContext:
      ulimits:
      - name: nofile
        soft: 65536
        hard: 65536

Kubernetes 中 livenessProbereadinessProbe 必须避开高负载路径

/healthz 这类轻量端点没问题,但若 probe 指向一个依赖数据库或外部 API 的健康检查接口,在流量高峰时可能因超时反复重启 Pod —— 实际服务仍存活,只是暂时慢。

  • 确保 readinessProbe 使用无依赖的本地检查(例如只检查 HttpContext.RequestServices.GetService<IHostApplicationLifetime>() 是否非 null)
  • 设置合理的 timeoutSeconds(建议 ≥3s)和 failureThreshold(建议 ≥3),避免瞬时 GC 或 JIT 编译导致误判
  • 禁用 livenessProbe 对 ASP.NET Core 默认 /healthz 的轮询,改用 startupProbe 配合就绪探针,防止启动慢的应用被过早 kill

Docker 镜像必须基于 mcr.microsoft.com/dotnet/aspnet 多阶段构建并关闭调试符号

使用 dotnet publish -c Release --self-contained false 构建后,若镜像仍含 .pdb 文件或启用了 Debug 配置,会显著增加内存占用、拖慢 JIT,并在 Kubernetes 中触发 OOMKilled。

  • Dockerfile 必须显式删除调试文件:
    RUN find /app -name "*.pdb" -delete
  • 禁用开发中间件:确保 app.UseDeveloperExceptionPage()app.UseExceptionHandler("/error") 仅在 IsDevelopment() 为 true 时注册
  • 优先使用 linux-musl 运行时镜像(如 8.0-alpine)降低基础镜像体积,但需验证第三方 native 依赖兼容性

HttpClient 必须注册为单例并复用,禁止在 using 块中创建

Kubernetes 下每个 HttpClient 实例会独占 socket 连接池,频繁 new 导致 SocketException: Too many open files,且 DNS 解析在容器内常缓存失效,加剧连接泄漏。

  • Program.cs 中统一注册:
    builder.Services.AddHttpClient<MyApiClient>(client =>
    {
        client.BaseAddress = new Uri(builder.Configuration["ApiBaseUrl"]);
    }).SetHandlerLifetime(TimeSpan.FromMinutes(5));
  • 避免手动调用 Dispose();由 DI 容器管理生命周期
  • 若需细粒度控制(如不同超时),用命名客户端 + IHttpClientFactory 获取,而非 new HttpClient()

实际部署中最容易被忽略的是容器内 DNS 缓存策略和 HttpClient 的 handler 复用粒度——它们不会立刻报错,但会在 1000+ QPS 持续 10 分钟后开始出现随机连接超时和 ServicePointManager 警告。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注