我们有一个 Elixir 应用程序经常被 Amazon ECS 终止,原因是“OutOfMemoryError:容器因内存使用而被终止”。
我们使用 Fargate 进行部署,并配有 8GB RAM 容器。我们同时运行 4 个实例。当发生 OutOfMemoryError 时,所有容器都会被杀死。我们使用 AWS 和 NewRelic 跟踪内存使用情况,并且内存从未接近容器允许的最大限制。此外,所有容器都会同时被杀死。看起来它只用 60% 的内存使用率就杀死了容器。
我们试图弄清楚为什么会发生这种情况以及我们可以采取哪些措施来防止这些意外的内存杀死事件。即使一个容器在接近 60% 时被杀死,我们也会比所有容器同时被杀死更好。
此图显示了 ECS 应用程序的内存利用率(平均)。您可以看到它在峰值时使用了大约 5GB 内存(蓝线),远低于保留内存(橙线)。绿线显示容器(任务)正在重新启动。
这是我们的任务定义的片段(必要时进行编辑):
{
"taskDefinitionArn": "our-task",
"containerDefinitions": [
{
"name": "our-application",
"image": "image-on-registry",
"cpu": 0,
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080,
"protocol": "tcp"
}
],
"essential": true,
"environment": []
}
],
"networkMode": "awsvpc",
"status": "ACTIVE",
"compatibilities": [
"EC2",
"FARGATE"
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "4096",
"memory": "8192"
}
这个问题已经困扰我们一段时间了,并且每隔一天都会导致停机。感谢您的帮助!
在我们启用java本机内存跟踪之后,我发现编译器空间急剧增加。
Before:
Compiler (reserved=1621KB, committed=1621KB)
(malloc=1488KB #5084)
(arena=133KB #5)
After:
Compiler (reserved=18257800KB, committed=18257800KB)
(malloc=1488KB #5085)
(arena=18256312KB #10)
我们使用的是 openjdk 11.0.16。经过一番小搜索,我发现 java 版本 11.0.16 中存在一个 bug,并且 openjdk 在 此版本之后就弃用了 java 11。我们转移到 amazon corretto 11.0.20 后问题就解决了。