资源监视涉及持续测量资源利用率值,例如 CPU、内存和网络使用情况。 Microsoft.Extensions.Diagnostics.ResourceMonitoring NuGet 包提供了一系列定制 API,专用于监视 .NET 应用程序的资源利用率。
可以采用两种方式使用度量值:
- 使用 .NET 指标。
- 使用IResourceMonitor接口。 此接口已弃用,因此请改用基于指标的方法。 如果仍需手动侦听指标值,请参阅 “迁移到基于指标的资源监视”。
重要说明
Microsoft.Extensions.Diagnostics.ResourceMonitoring 包会假定使用者将向 Microsoft.Extensions.Logging 包注册日志记录提供程序。 如果未注册日志记录,则调用 AddResourceMonitoring 将引发异常。 此外,按照指南配置类别的Debug日志级别Microsoft.Extensions.Diagnostics.ResourceMonitoring,可以启用内部库日志记录。
使用资源监视的 .NET 指标
若要使用资源监视库生成的 .NET 指标,请执行以下操作:
- 将 - Microsoft.Extensions.Diagnostics.ResourceMonitoring包添加到项目。
- 将资源监视服务添加到依赖项注入容器: - services.AddResourceMonitoring();
- 使用任何与 OpenTelemetry 兼容的指标收集器配置指标集合。 例如: - services.AddOpenTelemetry() .WithMetrics(builder => { builder.AddMeter("Microsoft.Extensions.Diagnostics.ResourceMonitoring"); builder.AddConsoleExporter(); // Or any other metrics exporter });
- 现在,可以通过配置的指标导出程序观察资源使用情况指标。 
有关可用指标的信息,请参阅 .NET 扩展指标:Microsoft.Extensions.Diagnostics.ResourceMonitoring。
有关指标集合的信息,请参阅 指标集合。
使用 IResourceMonitor 接口
谨慎
IResourceMonitor本节中所述的接口已弃用,可能会在 .NET 的未来版本中删除。 迁移到基于指标的方法。
该 IResourceMonitor 接口提供了用于检索有关进程资源利用率的实时信息的方法。 此接口支持检索与 CPU 和内存使用情况相关的数据,并且当前与 Windows 和 Linux 平台兼容。
示例资源监视使用情况
以下示例演示了如何使用 IResourceMonitor 接口检索有关当前进程的 CPU 和内存使用情况的信息。
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.ResourceMonitoring;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Spectre.Console;
var app = Host.CreateDefaultBuilder()
    .ConfigureServices(services =>
    {
        services.AddLogging(static builder => builder.AddConsole())
                .AddResourceMonitoring();
    })
    .Build();
var monitor = app.Services.GetRequiredService<IResourceMonitor>();
await app.StartAsync();
前面的代码:
- 实例化新的 ServiceCollection 实例,链接对扩展方法的 AddLogging 和 AddResourceMonitoring 的调用。
- 基于 ServiceCollection实例构建一个新的 ServiceProvider 实例。
- 从 ServiceProvider实例获取 IResourceMonitor 接口的实例。
此时,使用 IResourceMonitor 实现时,将使用 IResourceMonitor.GetUtilization 方法请求资源利用率。 GetUtilization 方法会返回 ResourceUtilization 实例,其中包含以下信息:
- ResourceUtilization.CpuUsedPercentage:CPU 使用率百分比。
- ResourceUtilization.MemoryUsedPercentage:内存使用量百分比。
- ResourceUtilization.MemoryUsedInBytes:内存使用量(以字节为单位)。
-               ResourceUtilization.SystemResources:系统资源。
- SystemResources.GuaranteedMemoryInBytes:保证的内存(以字节为单位)。
- SystemResources.MaximumMemoryInBytes:最大内存(以字节为单位)。
- SystemResources.GuaranteedCpuUnits:保证的 CPU(单位数)。
- SystemResources.MaximumCpuUnits:最大 CPU(单位数)。
 
使用 Spectre.Console 扩展资源监视
扩展此示例后,可以利用 Spectre.Console,这是一个备受推崇的 .NET 库,旨在简化具有视觉吸引力的跨平台控制台应用程序的开发。 借助 Spectre,你将能够以表格格式呈现资源利用率数据。 以下代码演示了如何使用 IResourceMonitor 接口访问有关当前进程的 CPU 和内存使用情况的详细信息,然后在表中显示此数据:
await StartMonitoringAsync(monitor, token);
async Task StartMonitoringAsync(IResourceMonitor monitor, CancellationToken cancellationToken)
{
    var table = new Table()
        .Centered()
        .Title("Resource Monitoring", new Style(foreground: Color.Purple, decoration: Decoration.Bold))
        .Caption("Updates every three seconds. *GTD: Guaranteed ", new Style(decoration: Decoration.Dim))
        .RoundedBorder()
        .BorderColor(Color.Cyan1)
        .AddColumns(
        [
            new TableColumn("Time").Centered(),
            new TableColumn("CPU %").Centered(),
            new TableColumn("Memory %").Centered(),
            new TableColumn("Memory (bytes)").Centered(),
            new TableColumn("GTD / Max Memory (bytes)").Centered(),
            new TableColumn("GTD / Max CPU (units)").Centered(),
        ]);
    await AnsiConsole.Live(table)
        .StartAsync(async ctx =>
        {
            var window = TimeSpan.FromSeconds(3);
            while (cancellationToken.IsCancellationRequested is false)
            {
                var utilization = monitor.GetUtilization(window);
                var resources = utilization.SystemResources;
                table.AddRow(
                    [
                        $"{DateTime.Now:T}",
                        $"{utilization.CpuUsedPercentage:p}",
                        $"{utilization.MemoryUsedPercentage:p}",
                        $"{utilization.MemoryUsedInBytes:#,#}",
                        $"{resources.GuaranteedMemoryInBytes:#,#} / {resources.MaximumMemoryInBytes:#,#}",
                        $"{resources.GuaranteedCpuUnits} / {resources.MaximumCpuUnits}",
                    ]);
                ctx.Refresh();
                await Task.Delay(window);
            }
        });
}
前面的代码:
- 创建取消令牌源和取消令牌。
- 创建一个新 Table实例,并使用标题、描述文字和列对其进行配置。
- 执行 Table实例的实时呈现,从而传入每三秒调用一次的委托。
- 从 IResourceMonitor实例获取当前资源利用率信息,并将其显示为Table实例中的新行。
下面是上述代码的输出示例:
有关此示例的源代码,请参阅资源监视示例。
迁移到基于指标的资源监视
由于 IResourceMonitor 接口已被弃用,因此请迁移到基于指标的方法。 Microsoft.Extensions.Diagnostics.ResourceMonitoring 包提供多个可改用的指标,例如:
- container.cpu.limit.utilization:正在运行的容器化应用程序的 CPU 消耗份额,相对于- [0, 1]范围内的资源限制。 适用于 Linux 和 Windows 上的容器化应用。
- container.cpu.request.utilization:正在运行的容器化应用程序的 CPU 消耗份额相对于- [0, 1]范围内的资源请求。 适用于 Linux 上的容器化应用。
- container.memory.limit.utilization:正在运行的容器化应用程序的内存消耗份额相对于范围- [0, 1]中的资源限制。 适用于 Linux 和 Windows 上的容器化应用。
有关可用指标的详细信息,请参阅 内置指标:Microsoft.Extensions.Diagnostics.ResourceMonitoring 部分。
迁移指南
本部分提供从已弃用 IResourceMonitor 的接口到基于指标的方法的迁移指南。 仅当手动侦听应用程序中的资源利用率指标时,才需要本指南。 在大多数情况下,无需手动侦听指标,因为它们是使用指标导出程序自动收集和导出到后端的,如 使用资源监视的 .NET 指标中所述。
如果有类似于 IResourceMonitor示例用法的代码,请按如下所示更新它:
await StartMonitoringAsync(logger, token);
async Task StartMonitoringAsync(ILogger logger, CancellationToken cancellationToken)
{
    var table = new Table()
        .Centered()
        .Title("Resource Monitoring", new Style(foreground: Color.Purple, decoration: Decoration.Bold))
        .RoundedBorder()
        .BorderColor(Color.Cyan1)
        .AddColumns(
        [
            new TableColumn("Time").Centered(),
            new TableColumn("CPU limit %").Centered(),
            new TableColumn("CPU request %").Centered(),
            new TableColumn("Memory limit %").Centered(),
        ]);
    const string rmMeterName = "Microsoft.Extensions.Diagnostics.ResourceMonitoring";
    using var meter = new Meter(rmMeterName);
    using var meterListener = new MeterListener
    {
        InstrumentPublished = (instrument, listener) =>
        {
            if (instrument.Meter.Name == rmMeterName &&
                instrument.Name.StartsWith("container."))
            {
                listener.EnableMeasurementEvents(instrument, null);
            }
        }
    };
    
    var samples = new Dictionary<string, double>();
    meterListener.SetMeasurementEventCallback<double>((instrument, value, _, _) =>
    {
        if (instrument.Meter.Name == rmMeterName)
        {
            samples[instrument.Name] = value;
        }
    });
    meterListener.Start();
    await AnsiConsole.Live(table)
        .StartAsync(async ctx =>
        {
            var window = TimeSpan.FromSeconds(5);
            while (cancellationToken.IsCancellationRequested is false)
            {
                meterListener.RecordObservableInstruments();
                table.AddRow(
                    [
                        $"{DateTime.Now:T}",
                        $"{samples["container.cpu.limit.utilization"]:p}",
                        $"{samples["container.cpu.request.utilization"]:p}",
                        $"{samples["container.memory.limit.utilization"]:p}",
                    ]);
                ctx.Refresh();
                await Task.Delay(window);
            }
        });
}
前面的代码:
- 创建取消令牌源和取消令牌。
- 创建一个新 Table实例,并使用标题、描述文字和列对其进行配置。
- 执行 Table实例的实时呈现,从而传入每三秒调用一次的委托。
- 使用具有该方法的回调集 SetMeasurementEventCallback获取当前资源利用率信息,并将其显示为实例中的Table新行。
下面是上述代码的输出示例:
有关此示例的完整源代码,请参阅 使用手动指标示例进行资源监视。
Kubernetes 探测
除了资源监视之外,存在于 Kubernetes 群集中的应用还会通过诊断探测来报告其运行状况。 Microsoft.Extensions.Diagnostics.Probes NuGet 包为 Kubernetes 探测提供支持。 它会外部化各种运行状况检查,以便与各种 Kubernetes 探测保持一致,例如:
- 运行情况
- 就绪
- 启动
该库将应用的当前运行状况传达给 Kubernetes 托管环境。 如果进程报告处于不正常状态,Kubernetes 不会向其发送任何流量,从而提供恢复或终止的进程时间。
要添加对 Kubernetes 探测的支持,请添加对 Microsoft.Extensions.Diagnostics.Probes 的包引用。 在 IServiceCollection 实例上,调用 AddKubernetesProbes。

