【问题标题】:.NET Core high memory usage in Docker (AWS ECS Fargate)Docker 中的 .NET Core 高内存使用率(AWS ECS Fargate)
【发布时间】:2019-03-04 22:45:28
【问题描述】:

这是应用程序的描述。我有一个运行 Hangfire 的控制台应用程序。有几个工作是重复的。尤其是一项工作,它会解析多个大型 XML 文件。我将此控制台应用程序部署为 AWS ECS Fargate ontainer。

每次重复作业运行时,容器内存使用量都会不断上升,直到应用程序变得无响应或 AWS 终止容器。这是 ECS(大)上的 16GB 容器,因此它应该能够处理我扔给它的任何东西。我可以说,一旦内存使用量接近 13GB,它就注定要失败了。

关键是我在本地运行这个应用程序,它的内存使用量从来没有很高。我将从我的工作站和下面的容器中发布几个示例日志。

感谢您的任何见解!

解析 XML:

  • 使用 XmlSerializer 放入 JSON 格式的对象
  • 使用 XDocument 浏览文档
  • 使用 XSD 文件生成类,然后使用 XmlSerializer 填充

这三个都在本地工作,但在服务器上使用大量内存。这些是不变的 XML 文件,我在本地和容器中运行完全相同的文件。

仅供参考:我已关闭容器上的服务器垃圾收集。那没用。

2019 年 3 月 5 日编辑

以下日志来自以下代码。它没有相当复杂的应用程序的全部气息。这段代码在一个用 Hangfire 注册的方法中,每天运行一次。它从 FTP 站点提取 XML 文件,然后基本上运行下面的代码来处理这些文件。每个文件的大小最多为 10 MB。

XmlSerializer serializer = new XmlSerializer(Model);
foreach (var file in files)
{
    Console.WriteLine($"Processing file: {file.Name}");
    Model model;
    using (XmlReader reader = XmlReader.Create(file.FullName, new XmlReaderSettings { CheckCharacters = false }))
    {
        model = (Model)serializer.Deserialize(reader);
    }
    SaveToDatabase(model);
    Console.WriteLine($"Application Memory Usage - Working: {Process.GetCurrentProcess()?.WorkingSet64 ?? 0}, Private: {Process.GetCurrentProcess()?.PrivateMemorySize64 ?? 0}");
}

工作站日志:

[13:52:58 INF] Processing file: price_feed_supplemental_002981.xml
[13:52:58 INF] Application Memory Usage - Working: 1.4 GB, Private: 1.6 GB
[13:52:58 INF] Processing file: price_feed_002982.xml
[13:53:01 INF] Application Memory Usage - Working: 1.4 GB, Private: 1.6 GB
[13:53:01 INF] Processing file: price_feed_supplemental_002982.xml
[13:53:01 INF] Application Memory Usage - Working: 1.4 GB, Private: 1.6 GB
[13:53:01 INF] Processing file: price_feed_002983.xml
[13:53:01 INF] Application Memory Usage - Working: 1.4 GB, Private: 1.6 GB
[13:53:01 INF] Processing file: price_feed_supplemental_002983.xml
[13:53:02 INF] Application Memory Usage - Working: 1.4 GB, Private: 1.6 GB
[13:53:02 INF] Processing file: price_feed_002984.xml

容器日志:

[19:05:35 INF] Application Memory Usage - Working: 1.9 GB, Private: 0.0 bytes
[19:05:35 INF] Processing file: price_feed_supplemental_002987.xml
[19:05:35 INF] Application Memory Usage - Working: 1.9 GB, Private: 0.0 bytes
[19:05:35 INF] Processing file: price_feed_supplemental_002988.xml
[19:05:35 INF] Application Memory Usage - Working: 1.9 GB, Private: 0.0 bytes
[19:05:35 INF] Processing file: price_feed_002988.xml
[19:05:40 INF] Application Memory Usage - Working: 1.9 GB, Private: 0.0 bytes
[19:05:40 INF] Processing file: price_feed_002989.xml
[19:05:43 INF] Application Memory Usage - Working: 2.1 GB, Private: 0.0 bytes
[19:05:43 INF] Processing file: price_feed_supplemental_002989.xml
[19:05:43 INF] Application Memory Usage - Working: 2.1 GB, Private: 0.0 bytes
[19:05:43 INF] Processing file: price_feed_supplemental_002990.xml
[19:05:43 INF] Application Memory Usage - Working: 2.1 GB, Private: 0.0 bytes
[19:05:43 INF] Processing file: price_feed_002990.xml
[19:05:51 INF] Application Memory Usage - Working: 2.6 GB, Private: 0.0 bytes
[19:05:51 INF] Processing file: price_feed_002991.xml
[19:05:57 INF] Application Memory Usage - Working: 2.2 GB, Private: 0.0 bytes
[19:05:57 INF] Processing file: price_feed_supplemental_002991.xml
[19:06:00 INF] Application Memory Usage - Working: 2.2 GB, Private: 0.0 bytes
[19:06:00 INF] Processing file: price_feed_002992.xml
[19:06:19 INF] Application Memory Usage - Working: 2.1 GB, Private: 0.0 bytes
[19:06:19 INF] Processing file: price_feed_supplemental_002992.xml
[19:06:21 INF] Application Memory Usage - Working: 2.3 GB, Private: 0.0 bytes
[19:06:21 INF] Uncompressing file: usa_LTSF_20190228_002993_001_INC.zip
[19:06:22 INF] Source file: price_feed_002993_1.xml
[19:06:22 INF] Source file: price_feed_supplemental_002993_8.xml
[19:06:23 INF] Source file: price_feed_supplemental_002993_11.xml
[19:06:23 INF] Source file: price_feed_002993_2.xml
[19:06:23 INF] Source file: price_feed_supplemental_002993_5.xml
[19:06:23 INF] Source file: price_feed_supplemental_002993_4.xml
[19:06:24 INF] Source file: price_feed_supplemental_002993_17.xml
[19:06:24 INF] Source file: price_feed_supplemental_002993_15.xml
[19:06:24 INF] Source file: price_feed_supplemental_002993_3.xml
[19:06:25 INF] Source file: price_feed_supplemental_002993_1.xml
[19:06:25 INF] Source file: price_feed_supplemental_002993_9.xml
[19:06:25 INF] Source file: price_feed_supplemental_002993_7.xml
[19:06:26 INF] Source file: price_feed_supplemental_002993_6.xml
[19:06:26 INF] Source file: price_feed_supplemental_002993_14.xml
[19:06:26 INF] Source file: price_feed_supplemental_002993_13.xml
[19:06:27 INF] Source file: price_feed_supplemental_002993_16.xml
[19:06:27 INF] Source file: price_feed_supplemental_002993_12.xml
[19:06:27 INF] Source file: price_feed_supplemental_002993_2.xml
[19:06:28 INF] Source file: price_feed_supplemental_002993_10.xml
[19:06:28 INF] Processing file: price_feed_002984.xml
[19:06:28 INF] Application Memory Usage - Working: 2.5 GB, Private: 0.0 bytes
[19:06:28 INF] Processing file: price_feed_supplemental_002984.xml
[19:06:28 INF] Application Memory Usage - Working: 2.5 GB, Private: 0.0 bytes
[19:06:28 INF] Processing file: price_feed_supplemental_002985.xml
[19:06:28 INF] Application Memory Usage - Working: 2.5 GB, Private: 0.0 bytes
[19:06:28 INF] Processing file: price_feed_002985.xml
[19:06:28 INF] Application Memory Usage - Working: 2.5 GB, Private: 0.0 bytes
[19:06:28 INF] Processing file: price_feed_supplemental_002986.xml
[19:06:28 INF] Application Memory Usage - Working: 2.5 GB, Private: 0.0 bytes
[19:06:28 INF] Processing file: price_feed_002986.xml
[19:06:28 INF] Application Memory Usage - Working: 2.5 GB, Private: 0.0 bytes
[19:06:28 INF] Processing file: price_feed_002987.xml
[19:06:30 INF] Application Memory Usage - Working: 2.6 GB, Private: 0.0 bytes
[19:06:30 INF] Processing file: price_feed_supplemental_002987.xml
[19:06:30 INF] Application Memory Usage - Working: 2.6 GB, Private: 0.0 bytes
[19:06:30 INF] Processing file: price_feed_supplemental_002988.xml
[19:06:30 INF] Application Memory Usage - Working: 2.6 GB, Private: 0.0 bytes
[19:06:30 INF] Processing file: price_feed_002988.xml
[19:06:35 INF] Application Memory Usage - Working: 2.9 GB, Private: 0.0 bytes
[19:06:35 INF] Processing file: price_feed_002989.xml
[19:06:38 INF] Application Memory Usage - Working: 3.1 GB, Private: 0.0 bytes
[19:06:38 INF] Processing file: price_feed_supplemental_002989.xml
[19:06:38 INF] Application Memory Usage - Working: 3.1 GB, Private: 0.0 bytes
[19:06:38 INF] Processing file: price_feed_supplemental_002990.xml
[19:06:38 INF] Application Memory Usage - Working: 3.1 GB, Private: 0.0 bytes
[19:06:38 INF] Processing file: price_feed_002990.xml
[19:06:47 INF] Application Memory Usage - Working: 3.7 GB, Private: 0.0 bytes
[19:06:47 INF] Processing file: price_feed_002991.xml
[19:06:53 INF] Application Memory Usage - Working: 4.1 GB, Private: 0.0 bytes
[19:06:53 INF] Processing file: price_feed_supplemental_002991.xml
[19:06:55 INF] Application Memory Usage - Working: 4.3 GB, Private: 0.0 bytes
[19:06:55 INF] Processing file: price_feed_002992.xml
[19:07:05 INF] Application Memory Usage - Working: 4.9 GB, Private: 0.0 bytes
[19:07:05 INF] Processing file: price_feed_supplemental_002992.xml
[19:07:07 INF] Application Memory Usage - Working: 5.0 GB, Private: 0.0 bytes
[19:07:07 INF] Processing file: price_feed_002993_1.xml
[19:09:40 INF] 1 servers were removed due to timeout
[19:10:49 INF] Application Memory Usage - Working: 10.0 GB, Private: 0.0 bytes
[19:10:49 INF] Processing file: price_feed_supplemental_002993_8.xml
[19:12:10 INF] Application Memory Usage - Working: 12.5 GB, Private: 0.0 bytes
[19:12:10 INF] Processing file: price_feed_supplemental_002993_11.xml
[19:13:08 INF] Application Memory Usage - Working: 13.5 GB, Private: 0.0 bytes
[19:13:08 INF] Processing file: price_feed_002993_2.xml
[19:14:06 INF] Application Memory Usage - Working: 13.8 GB, Private: 0.0 bytes
[19:14:06 INF] Processing file: price_feed_supplemental_002993_5.xml

【问题讨论】:

  • 如果您在本地机器上处理所有日志文件,内存会发生什么变化?您本地盒子的统计信息最多只显示002984.xml,并且之前的内存保持不变。在您的服务器上,您有几个文件的内存也保持不变。
  • 我没有包括所有本地日志,因为它们是所有本地日志的确切内存使用情况。这是在本地运行并通过 Visual Studio 的调试器运行,结果相同。
  • 我想知道这是否与blog post by Maoni 有关尼克遇到的问题有关。运行容器的机器的高核心数可能会导致堆在 GC 发生之前增长到大量。您能否通过定期调用GC.Collect 来检查是 GC 未运行还是内存泄漏?
  • 能否也分享一下这是什么版本的运行时等
  • @JohnD 这是在 .NET Core 2.2 下运行的。

标签: c# .net .net-core amazon-ecs hangfire


【解决方案1】:

通过将 <ServerGarbageCollection>false</ServerGarbageCollection> 添加到 Web 应用程序的 csproj 文件来禁用服务器垃圾收集(强制工作站垃圾收集)似乎使 GC 更急切,因此有助于保持堆小但不受管理的内存还在慢慢爬上来。它最终成为内存泄漏 - 静态方法通过引用将其参数之一传递回调用者,静态方法不由 GC 管理,因此每次调用此方法并提供更多字符串以枚举,对象通过参考越来越大。

我删除了传递引用,该方法现在正常返回对象(通过return),但我仍然必须在此静态方法中调用GC.Collect() 以防止大约 500MB-1GB 的瞬时峰值。通常,即使在生产环境中这也可以,因为 GC 确实会迅速将内存使用率恢复到正常水平,但是如果这些内存峰值中的一个导致 .NET 应用程序超出内存配额。

不用说,我们正在处理 O(N^2) 枚举中的一些大字符串,我怀疑在重写此方法后可以删除对 GC.Collect() 的调用。在您的情况下,您可能在某处遗漏了using,或者您正在使用事件(不太可能),或者像我一样,您有一个静态方法通过引用传递某些东西 - 或者不传递 - 并且该静态方法免于 GC,正在慢慢泄漏。

至于禁用的“服务器”垃圾收集,这似乎只是因为 Fargate/ECS 任务仅在一个 vCPU 上运行。有关服务器与工作站 GC 的更多信息,请参阅 here

Visual Studio 2022 的内置性能测量工具还可以,但是 VS 偶尔会崩溃(我的工作计算机也很弱),所以我最终使用了 Jetbrains 的 dotMemory,它具有更好的界面和更好的快照比较功能。

【讨论】:

    猜你喜欢
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 2021-01-24
    • 2021-12-10
    相关资源
    最近更新 更多