我正在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
还在docker-compose中尝试了以下操作:
mem_reservation: 128m
mem_limit: 256m
memswap_limit: 256m
(这些只会使它更快死亡)
尝试将以下内容设置为true或false,没有区别:
ServerGarbageCollection
我尝试改为作为Windows容器运行,这不是OOM,但它似乎也不遵守内存限制。
我已经排除了使用HttpClient和EF Core的可能性-因为在我的示例中甚至没有使用它们。我已经读过一些关于在端口443上监听的问题-因为我可以让容器整天处于空闲状态,如果我在一天结束时检查的话-它占用了更多的内存(不是很大的内存,但是增长)。
我的API中的示例:
// GET api/values/5
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return "You said: " + id;
}
使用Curl呼叫示例:
curl -X GET "https://localhost:44329/api/values/7" -H "accept: text/plain" --insecure
(重复约1000次)
预期:对于非常原始的请求,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"]
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
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
我在Windows上运行Docker CE Engine 18.0.9.1,在Ubuntu上运行18.06.1。确认-我也在Dotnet Core 2.1中尝试过。
我还在IIS Express中进行了尝试-进程达到55MB左右,这实际上是向多个线程发送垃圾邮件,等等。
完成所有操作后,它会减少到大约29-35MB。
答案 0 :(得分:0)
这可能是因为未执行垃圾回收(GC)。
看看这个未解决的问题,它看起来非常相似:
https://github.com/dotnet/runtime/issues/851
使Ubuntu 18.04.4
在虚拟机上工作的一种解决方案是使用工作站垃圾回收(GC):
<PropertyGroup>
<ServerGarbageCollection>false</ServerGarbageCollection>
</PropertyGroup>
https://github.com/dotnet/runtime/issues/851#issuecomment-644648315
https://github.com/dotnet/runtime/issues/851#issuecomment-438474207
https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/workstation-server-gc
这是另一个发现:
经过进一步的调查,我发现差异很大 服务器之间的可用逻辑CPU数量(80 vs 16)。经过一番谷歌搜索,我遇到了这个话题dotnet/runtime#622 引导我进行CPU / GC /线程设置的实验。
我在堆栈文件中使用--cpus constraint;明确设置 System.GC.Concurrent=true,System.GC.HeapCount=8, System.GC.NoAffinitize=true,System.Threading.ThreadPool.MaxThreads=16 在
runtimeconfig.template.json
文件中;将图片更新为3.1.301-bionic sdk和3.1.5-bionic asp.net runtime-我在一个 各种组合,所有这些都没有效果。只是申请 一直挂到OOMKilled。唯一可与Server GC配合使用的是
--cpuset-cpus
约束。当然,显式设置可用处理器不是 docker swarm模式的一个选项。但是我正在尝试 可用cpus查找任何规律性。在这里我有一些 有趣的事实。有趣的是,之前我已经镜像了另外3个后端 新服务器群集的服务,并且默认情况下它们都运行良好 设置。它们的内存限制设置为
600 Mb
,但实际上它们需要 约400 Mb
运行。只有消耗内存,事情才会出错 应用程序(我有两个),它需要3 Gb
来构建 内存结构并以6 Gb
约束运行。它可以在
[1, 35]
个可用cpus到 在cpus计数为36
时挂起。
https://github.com/dotnet/runtime/issues/851#issuecomment-645237830