0

我有一个如下的 Azure 应用服务计划,它应该有 7 GB 的内存。

P2V2
420 total ACU
7 GB memory
Dv2-Series compute equivalent
83.22 USD/Month (Estimated)

我正在使用它来托管具有单个 Continuous WebJob 的单个应用程序。当然有应用程序本身的网站,但我根本不使用它。

此外,我的服务计划中只有 1 个应用程序实例,因此不是因为多个实例共享总可用 7 GiB 内存。

服务计划有 2 个部署槽,1 个用于生产,1 个用于暂存。两个应用程序(生产中和暂存)都已关闭,因为 WebJob 可以在应用程序本身关闭时继续运行。

这是我看到的令人费解的地方。从应用服务计划概述页面中,它说我使用了大约 45% 的可用总内存。 在此处输入图像描述

但是我有时会遇到 OutOfMemoryException,所以我开始检查我的 WebJob 实际使用了多少内存。

事实证明,它使用了 2 GiB 可用物理内存中的 1.6 GiB,而不是我期望的 7 GiB。

我获取当前内存的方式是通过以下代码

var currentMemory = Process.GetCurrentProcess().PrivateMemorySize64;
var totalMemory = GC.GetGCMemoryInfo().TotalAvailableMemoryBytes;

根据此处的文档https://docs.microsoft.com/en-us/dotnet/api/system.gcmemoryinfo.totalavailablememorybytes?view=net-6.0#System_GCMemoryInfo_TotalAvailableMemoryBytes

此属性值将是 COMPlus_GCHeapHardLimit 环境变量的值,或 runtimeconfig.json 中的 Server.GC.HeapHardLimit 值(如果已设置)。

如果程序在容器中运行,则此值是容器大小的实现定义的一部分。

否则,该属性的值是上次垃圾收集发生时可供垃圾收集器使用的机器上的物理内存。

由于我没有设置环境变量 runtimeconfig.json 并且它不是容器,因此我认为GC.GetGCMemoryInfo().TotalAvailableMemoryBytes正确地返回了 VM 上我的 WebJob 可用的总物理内存,即 2 GiB。

感谢 Vova 在下面的评论,我还找到了这篇文章。https://docs.microsoft.com/en-us/azure/app-service/faq-availability-performance-application-issues#i-see-the-message--worker-process-requested-recycle-due-to --percent-memory--limit---how-do-i-address-this-issue-

这确实有道理;同时,在我看来,这篇文章是针对应用服务本身的。WebJob 作为独立于网站的进程运行。虽然症状是一样的。看来我的 WebJob 是 JIT 到 32 位而不是 64 位。

我的 WebJob 构建配置

.NET 6 Console Application
Platform: Any CPU

无论如何,我的应用服务配置设置为 x64,如下所示。 在此处输入图像描述

我试图了解我做错了什么,因为我认为 Azure 在这里做的是正确的事情。

我正在使用 Azure 应用服务来运行 WebJob,因此我的目标是使用最小/最便宜的 SKU 来最大化 WebJob 的可用内存。

4

1 回答 1

0

我发现问题在于我如何通过run.cmd我在 ADO 管道中创建的启动脚本运行我的 WebJob。

dotnet MyWebJob.dll结果GC.GetGCMemoryInfo().TotalAvailableMemoryBytes返回 2 GiB 作为我的 WeJob 的总可用内存,而我的 WebJob 本身Process.GetCurrentProcess().PrivateMemorySize64仅消耗 1.5 GiB 的内存。

由于我的 ADO 管道还为 Windows 平台生成了一个可执行文件,因此我也有一个可以运行的 EXE。通过调用 EXEMyWebJob.exe结果来启动我的 WebJob,GC.GetGCMemoryInfo().TotalAvailableMemoryBytes返回 5.5 GiB 作为我的 WeJob 的总可用内存,而我的 WebJob 本身Process.GetCurrentProcess().PrivateMemorySize64膨胀到 3.5 GiB 的内存。

这两种不同行为的原因是Path环境变量同时包含 dotnet SDK x86 和 x64,其中 dotnet x86 在值中位于 dotnet x64 之前。结果,当我这样做时dotnet MyWebJob.dll,系统正在使用 x86 dotnet 运行时,这在调试控制台中很明显。

C:\home>dotnet --info
.NET SDK (reflecting any global.json):
 Version:   6.0.100
 Commit:    9e8b04bbff

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.14393
 OS Platform: Windows
 RID:         win10-x86
 Base Path:   C:\Program Files (x86)\dotnet\sdk\6.0.100\

Host (useful for support):
  Version: 6.0.0
  Commit:  4822e3c3aa

我修改了负责为我的 WebJob 生成启动脚本的 ADO 任务,以明确使用 x64 版本的 dotnet。[01/07/2022 00:21:06 > 52cb62: INFO] C:\local\Temp\jobs\continuous\MyWebJob\n04q3opt.krt>"C:\Program Files\dotnet\dotnet.exe" MyWebJob.dll 这解决了这个问题。

结果与上面显示的不使用直接运行 EXE 相同dotnet

于 2022-01-06T22:58:23.750 回答