Поделиться через


Мониторинг ресурсов

Мониторинг ресурсов включает непрерывное измерение значений использования ресурсов, таких как ЦП, память и использование сети. Пакет NuGet Microsoft.Extensions.Diagnostics.ResourceMonitoring предлагает коллекцию API, адаптированных для мониторинга использования ресурсов приложений .NET.

Эти показатели могут использоваться двумя способами:

Внимание

В пакете Microsoft.Extensions.Diagnostics.ResourceMonitoring предполагается, что потребитель будет регистрировать поставщиков ведения журнала в пакете Microsoft.Extensions.Logging . Если вы не регистрируете ведение журнала, вызов AddResourceMonitoring вызовет исключение. Кроме того, вы можете включить ведение журнала внутренней библиотеки, настроив Debug уровень журнала для категории, как показано в руководствеMicrosoft.Extensions.Diagnostics.ResourceMonitoring.

Использование метрик .NET для мониторинга ресурсов

Чтобы использовать метрики .NET, созданные библиотекой мониторинга ресурсов, выполните следующие действия.

  1. Добавьте пакет Microsoft.Extensions.Diagnostics.ResourceMonitoring в проект.

  2. Добавьте службы мониторинга ресурсов в контейнер внедрения зависимостей:

    services.AddResourceMonitoring();
    
  3. Настройте коллекцию метрик с помощью любого сборщика метрик, совместимых с OpenTelemetry. Рассмотрим пример.

    services.AddOpenTelemetry()
        .WithMetrics(builder =>
        {
            builder.AddMeter("Microsoft.Extensions.Diagnostics.ResourceMonitoring");
            builder.AddConsoleExporter(); // Or any other metrics exporter
        });
    
  4. Теперь вы можете наблюдать метрики использования ресурсов с помощью настроенного экспортера метрик.

Сведения о доступных метриках см. в разделе метрики расширений .NET: Microsoft.Extensions.Diagnostics.ResourceMonitoring.

Сведения о коллекции метрик см. в коллекции метрик.

Используйте интерфейс IResourceMonitor

Осторожность

Интерфейс IResourceMonitor , описанный в этом разделе, устарел и может быть удален в будущих версиях .NET. Переход к подходу на основе метрик.

Интерфейс IResourceMonitor предоставляет методы для получения сведений в режиме реального времени об использовании ресурсов процесса. Этот интерфейс поддерживает получение данных, связанных с использованием ЦП и памяти, и в настоящее время совместимо с платформами Windows и Linux.

Пример использования мониторинга ресурсов

В следующем примере показано, как использовать IResourceMonitor интерфейс для получения сведений об использовании ЦП и памяти текущего процесса.

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 методов расширения.
  • Создает новый ServiceProvider экземпляр из экземпляра ServiceCollection .
  • Возвращает экземпляр IResourceMonitor интерфейса из экземпляра ServiceProvider .

На этом этапе с реализацией IResourceMonitor вы будете запрашивать использование ресурсов с IResourceMonitor.GetUtilization помощью метода. Метод GetUtilization возвращает ResourceUtilization экземпляр, содержащий следующие сведения:

Расширение мониторинга ресурсов с помощью Spectre.Console

Расширяя этот пример, вы можете использовать Spectre.Console, хорошо известную библиотеку .NET, предназначенную для упрощения разработки визуальных приложений кроссплатформенных консольных приложений. С помощью Spectre вы сможете представить данные об использовании ресурсов в табличном формате. Следующий код иллюстрирует использование IResourceMonitor интерфейса для получения сведений об использовании ЦП и памяти текущего процесса, а затем представление этих данных в таблице:

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 .

Ниже приведен пример выходных данных из предыдущего кода:

Пример выходных данных приложения мониторинга ресурсов.

Исходный код этого примера см. в примере мониторинга ресурсов.

Перейти на мониторинг ресурсов на основе метрик

Поскольку интерфейс устарел, перейдите к подходу на основе метрик. Пакет Microsoft.Extensions.Diagnostics.ResourceMonitoring предоставляет несколько метрик, которые можно использовать вместо этого, например:

  • container.cpu.limit.utilization: доля потребления ЦП запущенного контейнерного приложения относительно ограничения ресурсов в диапазоне [0, 1]. Доступно для контейнерных приложений в Linux и Windows.
  • container.cpu.request.utilization: доля потребления ЦП запущенного контейнерного приложения относительно запроса ресурсов в диапазоне [0, 1]. Доступно для контейнерных приложений в Linux.
  • container.memory.limit.utilization: общий ресурс потребления памяти запущенного контейнерного приложения относительно ограничения ресурсов в диапазоне [0, 1]. Доступно для контейнерных приложений в Linux и Windows.

Дополнительные сведения о доступных метриках см. в разделе "Встроенные метрики: Microsoft.Extensions.Diagnostics.ResourceMonitoring ".

Руководство по миграции

В этом разделе приведено руководство по миграции из устаревшего IResourceMonitor интерфейса в подход на основе метрик. Это руководство необходимо только в том случае, если вы вручную прослушиваете метрики использования ресурсов в приложении. В большинстве случаев вам не нужно слушать метрики вручную, так как они автоматически собираются и экспортируются в серверные части с помощью экспортеров метрик, как описано в разделе "Использование метрик мониторинга ресурсов".

Если у вас есть код, аналогичный 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, сообщают о работоспособности с помощью диагностических проб. Пакет NuGet Microsoft.Extensions.Diagnostics.Probes обеспечивает поддержку проб Kubernetes. Она выполняет различные проверки работоспособности, которые соответствуют различным пробам Kubernetes, например:

  • Живость
  • Готовность
  • Запуск

Библиотека передает текущее состояние приложения в среду размещения Kubernetes. Если процесс сообщает о неработоспособном состоянии, Kubernetes не отправляет его трафик, предоставляя время процесса для восстановления или завершения.

Чтобы добавить поддержку проб Kubernetes, добавьте ссылку на пакет в Microsoft.Extensions.Diagnostics.Probes. В экземпляре IServiceCollection вызовите AddKubernetesProbes.

См. также