Dotnet核心Docker容器泄漏Linux上的RAM并导致OOM

Pet*_*lls 8 c# linux ubuntu docker .net-core

我在Docker的Linux容器中运行Dotnet Core 2.2。

我尝试了许多不同的配置/环境选项-但是我仍然回到内存不足的问题('docker events'报告OOM)。

在生产中,我托管在Ubuntu上。对于开发,我在Windows的Docker上使用Linux容器(MobyLinux)。

我已经回到运行Web API模板项目,而不是我的实际应用程序。我从字面上返回一个字符串,什么也不做。如果我称它为卷曲的大约1000倍,则容器将死亡。垃圾收集器似乎根本没有工作。

尝试在docker-compose中设置以下环境变量:

DOTNET_RUNNING_IN_CONTAINER=true
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true
ASPNETCORE_preventHostingStartup=true
Run Code Online (Sandbox Code Playgroud)

还可以在docker-compose中尝试以下操作:

mem_reservation: 128m
mem_limit: 256m
memswap_limit: 256m
Run Code Online (Sandbox Code Playgroud)

(这些只会使它更快死掉)

尝试将以下内容设置为true或false,没有区别:

ServerGarbageCollection
Run Code Online (Sandbox Code Playgroud)

我尝试改为作为Windows容器运行,这不是OOM-但它似乎也不尊重内存限制。

我已经排除了使用HttpClient和EF Core的可能性-因为在我的示例中甚至没有使用它们。我已经读过一些关于在端口443上监听的问题-因为我可以让容器整天处于空闲状态,如果我在一天结束时进行检查-它占用了更多的内存(不是很大,但是增长)。

我的API中的示例:

// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "You said: " + id;
}
Run Code Online (Sandbox Code Playgroud)

用Curl调用示例:

curl -X GET "https://localhost:44329/api/values/7" -H  "accept: text/plain" --insecure
Run Code Online (Sandbox Code Playgroud)

(重复1,000次左右)

预期:对于非常原始的请求,RAM使用率保持较低

实际:RAM使用率持续增长,直到出现故障

完整的Dockerfile:

FROM microsoft/dotnet:2.2-aspnetcore-runtime AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM microsoft/dotnet:2.2-sdk AS build
WORKDIR /src
COPY ["WebApplication1/WebApplication1.csproj", "WebApplication1/"]
RUN dotnet restore "WebApplication1/WebApplication1.csproj"
COPY . .
WORKDIR "/src/WebApplication1"
RUN dotnet build "WebApplication1.csproj" -c Release -o /app

FROM build AS publish
RUN dotnet publish "WebApplication1.csproj" -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "WebApplication1.dll"]
Run Code Online (Sandbox Code Playgroud)

docker-compose.yml

version: '2.3'

services:
  webapplication1:
    image: ${DOCKER_REGISTRY-}webapplication1
    mem_reservation: 128m
    mem_limit: 256m
    memswap_limit: 256m
    cpu_percent: 25
    build:
      context: .
      dockerfile: WebApplication1/Dockerfile
Run Code Online (Sandbox Code Playgroud)

docker-compose.override.yml

version: '2.3'

services:
  webapplication1:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ASPNETCORE_URLS=https://+:443;http://+:80
      - ASPNETCORE_HTTPS_PORT=44329
      - DOTNET_RUNNING_IN_CONTAINER=true
      - DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=true
      - ASPNETCORE_preventHostingStartup=true
    ports:
      - "50996:80"
      - "44329:443"
    volumes:
      - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro
      - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro
Run Code Online (Sandbox Code Playgroud)

我在Windows上运行Docker CE Engine 18.0.9.1,在Ubuntu上运行18.06.1。确认-我也在Dotnet Core 2.1中尝试过。

我也尝试过在IIS Express中使用-进程达到55MB左右,这实际上是在向多个线程发送垃圾邮件等。

完成所有操作后,它会减少到大约29-35MB。

Ogg*_*las 2

这可能是因为未执行垃圾收集 (GC)。

\n

看看这个未解决的问题,它看起来非常相似:

\n

https://github.com/dotnet/runtime/issues/851

\n

Ubuntu 18.04.4在虚拟机上运行的一种解决方案是使用工作站垃圾收集 (GC):

\n
<PropertyGroup>\n    <ServerGarbageCollection>false</ServerGarbageCollection>\n</PropertyGroup>\n
Run Code Online (Sandbox Code Playgroud)\n

https://github.com/dotnet/runtime/issues/851#issuecomment-644648315

\n

https://github.com/dotnet/runtime/issues/851#issuecomment-438474207

\n

https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/workstation-server-gc

\n

这是另一个发现:

\n
\n

经过进一步调查,我发现我的服务器之间的可用逻辑 CPU 数量存在很大差异(80 与 16)。经过一番谷歌搜索后,我发现了这个主题dotnet/runtime#622 \n这引导我对 CPU/GC/Threads 设置进行实验。

\n

我在堆栈文件中使用--cpus 约束;显式设置\n System.GC.Concurrent=trueSystem.GC.HeapCount=8、\n System.GC.NoAffinitize=trueSystem.Threading.ThreadPool.MaxThreads=16 \nruntimeconfig.template.json文件;将映像更新为3.1.301-bionic\nsdk3.1.5-bionic asp.net 运行时\xe2\x80\x94 我以各种组合制作了所有这些东西,但所有这些都没有效果。应用程序\n会挂起直到 OOMKilled。

\n

使其与服务器 GC 一起使用的唯一因素是--cpuset-cpus\n约束。当然,对于 docker swarm 模式来说,显式设置可用处理器并不是\n选项。但我正在尝试使用可用的 cpu 来发现任何规律性。在这里我得到了一些\n有趣的事实。

\n

有趣的是,之前我已将 3 个其他后端服务迁移到新的服务器集群,它们都与默认设置配合良好。它们的内存限制设置为600 Mb,但实际上它们需要400 Mb运行。只有消耗内存的应用程序才会出现问题(我有两个),它需要3 Gb构建内存结构并在6 Gb约束下运行。

\n

它在可用 cpu 之间的任何范围内保持工作[1, 35],并在 cpu 计数为\n时挂起36

\n
\n

https://github.com/dotnet/runtime/issues/851#issuecomment-645237830

\n