ASP.NET Core의 상태 검사

Glenn Condron, Juergen Gutsch

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

ASP.NET Core는 앱 인프라 구성 요소의 상태를 보고하기 위해 상태 검사 미들웨어와 라이브러리를 제공합니다.

상태 검사는 앱에 의해 HTTP 엔드포인트로서 노출됩니다. 상태 검사 엔드포인트는 다양한 실시간 모니터링 시나리오에 맞게 구성할 수 있습니다.

  • 상태 프로브는 컨테이너 오케스트레이터와 부하 분산 장치가 앱 상태를 검사하는 데 사용할 수 있습니다. 예를 들어, 컨테이너 오케스트레이터는 롤링 배포를 중지하거나 컨테이너를 다시 시작하여 실패한 상태 검사에 응답할 수 있습니다. 부하 분산 장치는 장애가 발생한 상태 검사 인스턴스로부터 트래픽을 다른 곳으로 라우팅하여 비정상 앱에 대응할 수 있습니다.
  • 메모리, 디스크 및 기타 물리적 서버 리소스의 사용이 정상적인 상태인지 모니터링할 수 있습니다.
  • 상태 검사는 데이터베이스 및 외부 서비스 엔드포인트와 같은 앱 종속성을 테스트하여 가용성 및 정상 작동 여부를 확인할 수 있습니다.

상태 검사는 일반적으로 외부 모니터링 서비스 또는 컨테이너 오케스트레이터와 함께 사용되어 앱 상태를 검사합니다. 앱에 상태 검사를 추가하기 전에 사용할 모니터링 시스템을 결정합니다. 모니터링 시스템은 어떤 유형의 상태 검사를 만들고 그 엔드포인트를 구성하는 방법을 지정합니다.

기본 상태 프로브

많은 앱의 경우, 요청을 처리할 수 있는 앱의 가용성(활동성)을 보고하는 기본 상태 검사 구성으로 앱 상태를 충분히 파악할 수 있습니다.

기본 구성은 상태 검사 서비스를 등록하고 상태 검사 미들웨어를 호출하여 URL 엔드포인트에서 상태 응답을 사용하여 응답합니다. 기본적으로 특정 종속성이나 하위 시스템을 테스트하기 위해 특정 상태 검사가 등록되지 않습니다. 앱은 상태 엔드포인트 URL에서 응답할 수 있는 경우 정상으로 간주됩니다. 기본 응답 기록기는 HealthStatus를 클라이언트에 일반 텍스트 응답으로 씁니다. HealthStatusHealthStatus.Healthy, HealthStatus.Degraded 또는 HealthStatus.Unhealthy입니다.

Program.csAddHealthChecks에 상태 검사 서비스를 등록합니다. MapHealthChecks를 호출하여 상태 검사 엔드포인트를 만듭니다.

다음 예제에서는 /healthz에서 상태 검사 엔드포인트를 만듭니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/healthz");

app.Run();

Docker HEALTHCHECK

Docker는 기본 상태 검사 구성을 사용하는 앱의 상태를 검사하는 데 사용할 수 있는 기본 제공 HEALTHCHECK 지시문을 제공합니다.

HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit

앞의 예제에서는 curl을 사용하여 /healthz에서 상태 검사 엔드포인트에 대한 HTTP 요청을 수행합니다. curl은 .NET Linux 컨테이너 이미지에 포함되지 않지만 Dockerfile에서 필요한 패키지를 설치하여 추가할 수 있습니다. Alpine Linux를 기반으로 하는 이미지를 사용하는 컨테이너는 curl 대신 포함된 wget을 사용할 수 있습니다.

상태 검사 만들기

상태 검사는 IHealthCheck 인터페이스를 구현하여 만듭니다. CheckHealthAsync 메서드는 상태를 Healthy, Degraded 또는 Unhealthy로 나타내는 HealthCheckResult를 반환합니다. 결과는 구성 가능한 상태 코드가 포함된 일반 텍스트 응답으로 작성됩니다. 구성은 상태 검사 옵션 섹션에 설명되어 있습니다. HealthCheckResult는 선택 사항인 키-값 쌍을 반환할 수도 있습니다.

다음 예제에서는 상태 검사의 레이아웃을 보여줍니다.

public class SampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

상태 검사의 논리는 CheckHealthAsync 메서드에 배치됩니다. 앞의 예제에서는 더미 변수 isHealthytrue로 설정합니다. isHealthy 값이 false로 설정되면 HealthCheckRegistration.FailureStatus 상태가 반환됩니다.

CheckHealthAsync가 검사 중에 예외를 throw하면 해당 HealthReportEntry.StatusFailureStatus로 설정된 상태로 새 HealthReportEntry가 반환됩니다. 이 상태는 AddCheck에 의해 정의되며(상태 검사 서비스 등록 섹션 참조) 검사 실패를 초래한 내부 예외가 포함되어 있습니다. Description은 예외의 메시지로 설정됩니다.

상태 검사 서비스 등록

상태 검사 서비스를 등록하려면 Program.cs에서 AddCheck를 호출합니다.

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>("Sample");

다음 예제에 표시된 AddCheck 오버로드는 상태 검사에서 오류가 보고되면 보고하도록 오류 상태(HealthStatus)를 설정합니다. 오류 상태가 null(기본값)로 설정되면 HealthStatus.Unhealthy가 보고됩니다. 이 오버로드는 라이브러리 작성자에게 유용한 시나리오입니다. 이 라이브러리에서는 상태 검사 구현이 설정을 준수하는 경우 상태 검사 실패가 발생할 때 라이브러리가 나타내는 오류 상태는 앱에 의해 적용됩니다.

상태 검사를 필터링하기 위해 태그를 사용할 수 있습니다. 태그는 상태 검사 필터링 섹션에 설명되어 있습니다.

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" });

AddCheck는 람다 함수를 실행할 수도 있습니다. 다음 예제에서 상태 검사는 항상 정상 결과를 반환합니다.

builder.Services.AddHealthChecks()
    .AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));

AddTypeActivatedCheck를 호출하여 상태 검사 구현에 인수를 전달합니다. 다음 예제에서 형식 활성화 상태 검사는 해당 생성자의 정수 및 문자열을 허용합니다.

public class SampleHealthCheckWithArgs : IHealthCheck
{
    private readonly int _arg1;
    private readonly string _arg2;

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // ...

        return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
    }
}

위의 상태 검사를 등록하려면 인수로 전달된 정수 및 문자열을 사용하여 AddTypeActivatedCheck를 호출합니다.

builder.Services.AddHealthChecks()
    .AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" },
        args: new object[] { 1, "Arg" });

상태 검사 라우팅 사용

Program.cs에서 엔드포인트 URL 또는 상대 경로를 사용하여 엔드포인트 작성기에 MapHealthChecks를 호출합니다.

app.MapHealthChecks("/healthz");

호스트 필요

RequireHost를 호출하여 상태 검사 엔드포인트에 대해 허용된 호스트를 하나 이상 지정합니다. 호스트는 punycode가 아닌 유니코드여야 하고 포트를 포함할 수 있습니다. 컬렉션을 제공하지 않으면 모든 호스트가 허용됩니다.

app.MapHealthChecks("/healthz")
    .RequireHost("www.contoso.com:5001");

상태 검사 엔드포인트가 특정 포트에서만 응답하도록 제한하려면 RequireHost에 대한 호출에서 포트를 지정합니다. 이 방법은 일반적으로 컨테이너 환경에서 서비스 모니터링을 위해 포트를 노출하는 데 사용됩니다.

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001");

Warning

호스트 헤더(예: HttpRequest.HostRequireHost)를 사용하는 API는 클라이언트에서 스푸핑될 수 있습니다.

호스트 및 포트 스푸핑을 방지하려면 다음 방법 중 하나를 사용합니다.

권한이 없는 클라이언트가 포트를 스푸핑하지 못하도록 하려면 다음을 호출 RequireAuthorization합니다.

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001")
    .RequireAuthorization();

자세한 내용은 RequireHost가 있는 경로에서 호스트 일치를 참조하세요.

권한 부여 필요

RequireAuthorization을 호출하여 상태 검사 요청 엔드포인트에서 권한 부여 미들웨어를 실행합니다. RequireAuthorization 오버로드는 하나 이상의 권한 부여 정책을 허용합니다. 정책을 제공하지 않으면 기본 권한 부여 정책이 사용됩니다.

app.MapHealthChecks("/healthz")
    .RequireAuthorization();

원본 간 요청(CORS) 사용

브라우저에서 수동으로 상태 검사를 실행하는 것이 일반적이지는 않지만, 상태 검사 엔드포인트에 RequireCors를 호출하여 CORS 미들웨어를 사용하도록 설정할 수 있습니다. RequireCors 오버로드는 CORS 정책 작성기 대리자(CorsPolicyBuilder) 또는 정책 이름을 허용합니다. 자세한 내용은 ASP.NET Core에서 CORS(원본 간 요청) 사용을 참조하세요.

상태 검사 옵션

HealthCheckOptions는 다음과 같은 상태 검사 동작을 사용자 지정할 수 있는 기회를 제공합니다.

상태 검사 필터링

기본적으로 상태 검사 미들웨어는 등록된 모든 상태 검사를 실행합니다. 상태 검사 하위 세트를 실행하려면 Predicate 옵션에 부울 값을 반환하는 함수를 제공합니다.

다음 예제에서는 sample 태그가 지정된 상태 검사만 실행되도록 상태 검사를 필터링합니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});

HTTP 상태 코드 사용자 지정

ResultStatusCodes를 사용하여 상태를 HTTP 상태 코드에 매핑하는 작업을 사용자 지정할 수 있습니다. 다음 StatusCodes 할당은 미들웨어에서 사용되는 기본값입니다. 요구 사항에 맞게 상태 코드 값을 변경합니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResultStatusCodes =
    {
        [HealthStatus.Healthy] = StatusCodes.Status200OK,
        [HealthStatus.Degraded] = StatusCodes.Status200OK,
        [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
    }
});

캐시 헤더 표시 안 함

AllowCachingResponses는 응답 캐싱을 방지하기 위해 상태 검사 미들웨어가 HTTP 헤더를 프로브 응답에 추가할지 여부를 제어합니다. 값이 false(기본값)인 경우 미들웨어는 응답 캐싱을 방지하기 위해 Cache-Control, ExpiresPragma 헤더를 설정하거나 재정의합니다. 값이 true인 경우 미들웨어는 응답 캐시 헤더를 수정하지 않습니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    AllowCachingResponses = true
});

출력 사용자 지정

상태 검사 보고서의 출력을 사용자 지정하려면 HealthCheckOptions.ResponseWriter 속성을 응답을 작성하는 대리자로 설정합니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResponseWriter = WriteResponse
});

기본 대리자는 HealthReport.Status의 문자열 값을 사용하여 최소 일반 텍스트 응답을 기록합니다. 다음 사용자 지정 대리자는 System.Text.Json을 사용하여 사용자 지정 JSON 응답을 출력합니다.

private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions { Indented = true };

    using var memoryStream = new MemoryStream();
    using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
    {
        jsonWriter.WriteStartObject();
        jsonWriter.WriteString("status", healthReport.Status.ToString());
        jsonWriter.WriteStartObject("results");

        foreach (var healthReportEntry in healthReport.Entries)
        {
            jsonWriter.WriteStartObject(healthReportEntry.Key);
            jsonWriter.WriteString("status",
                healthReportEntry.Value.Status.ToString());
            jsonWriter.WriteString("description",
                healthReportEntry.Value.Description);
            jsonWriter.WriteStartObject("data");

            foreach (var item in healthReportEntry.Value.Data)
            {
                jsonWriter.WritePropertyName(item.Key);

                JsonSerializer.Serialize(jsonWriter, item.Value,
                    item.Value?.GetType() ?? typeof(object));
            }

            jsonWriter.WriteEndObject();
            jsonWriter.WriteEndObject();
        }

        jsonWriter.WriteEndObject();
        jsonWriter.WriteEndObject();
    }

    return context.Response.WriteAsync(
        Encoding.UTF8.GetString(memoryStream.ToArray()));
}

상태 검사 API는 사용자가 선택한 모니터링 시스템에만 적용되는 형식이므로 복합 JSON 반환 형식에 대한 기본 제공 지원을 제공하지 않습니다. 앞의 예제에서 응답을 필요에 따라 사용자 지정합니다. System.Text.Json을 사용한 JSON 직렬화에 대한 자세한 내용은 .NET에서 JSON을 직렬화 및 역직렬화하는 방법을 참조하세요.

데이터베이스 프로브

상태 검사는 데이터베이스 쿼리를 지정하여 데이터베이스가 정상적으로 응답하는지를 나타내기 위해 부울 테스트로서 실행할 수 있습니다.

ASP.NET Core 앱에 대한 상태 검사 라이브러리인 AspNetCore.Diagnostics.HealthChecks에는 SQL Server 데이터베이스에 대해 실행되는 상태 검사가 포함됩니다. AspNetCore.Diagnostics.HealthChecks는 데이터베이스에 연결이 양호한지 확인하기 위해 데이터베이스에 대해 SELECT 1 쿼리를 실행합니다.

Warning

쿼리로 데이터베이스 연결을 검사할 때 신속하게 반환되는 쿼리를 선택합니다. 쿼리 방식 실행은 데이터베이스의 오버로드와 성능 저하를 유발할 수 있습니다. 대부분의 경우 테스트 쿼리를 실행할 필요가 없습니다. 간단히 데이터베이스에 연결하는 정도로도 충분합니다. 쿼리를 실행해야 하는 경우 SELECT 1과 같은 간단한 SELECT 쿼리를 선택합니다.

이 SQL Server 상태 검사를 사용하려면 AspNetCore.HealthChecks.SqlServer NuGet 패키지에 대한 패키지 참조를 포함합니다. 다음 예제에서는 SQL Server 상태 검사를 등록합니다.

var conStr = builder.Configuration.GetConnectionString("DefaultConnection");
if (string.IsNullOrEmpty(conStr))
{
    throw new InvalidOperationException(
                       "Could not find a connection string named 'DefaultConnection'.");
}
builder.Services.AddHealthChecks()
    .AddSqlServer(conStr);

참고 항목

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

Entity Framework Core DbContext 프로브

DbContext 검사는 앱이 EF CoreDbContext에 대해 구성된 데이터베이스와 통신할 수 있음을 확인합니다. DbContext 검사는 다음과 같은 앱에서 지원됩니다.

AddDbContextCheckDbContext에 대한 상태 검사를 등록합니다. DbContext는 메서드에 TContext로 제공됩니다. 오버로드는 오류 상태, 태그 및 사용자 지정 테스트 쿼리를 구성할 수 있습니다.

기본적으로:

  • DbContextHealthCheck는 EF Core의 CanConnectAsync 메서드를 호출합니다. AddDbContextCheck 메서드 오버로드를 사용하여 상태를 검사할 때 실행되는 작업을 사용자 정의할 수 있습니다.
  • 상태 검사의 이름은 TContext 형식의 이름입니다.

다음 예제에서는 DbContext 및 연결된 DbContextHealthCheck를 등록합니다.

builder.Services.AddDbContext<SampleDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddHealthChecks()
    .AddDbContextCheck<SampleDbContext>();

별도의 준비 상태 및 활동성 프로브

일부 호스팅 시나리오에서 두 가지 앱 상태를 구분하는 한 쌍의 상태 검사가 사용됩니다.

  • ‘준비 상태’는 앱이 정상적으로 실행 중이지만 요청을 받을 준비가 되지 않았음을 나타냅니다.
  • ‘활동성’은 앱의 작동이 중단되어 다시 시작해야 함을 나타냅니다.

다음 예제를 고려하세요. 앱은 요청을 처리할 준비가 되기 전에 큰 구성 파일을 다운로드해야 합니다. 앱에서 파일 다운로드를 여러 번 다시 시도할 수 있으므로 초기 다운로드가 실패하더라도 앱을 다시 시작하지 않는 것이 좋습니다. 활동성 프로브를 사용하여 프로세스의 활동성을 설명하며 다른 검사를 실행하지 않습니다. 또한 구성 파일이 다운로드되기 전에는 앱에 요청을 보내지 못하게 합니다. ‘준비 상태 프로브’를 사용하여 다운로드에 성공하여 앱이 요청을 받을 준비가 될 때까지 “준비되지 않음” 상태를 표시합니다.

다음 백그라운드 작업은 약 15초가 걸리는 시작 프로세스를 시뮬레이션합니다. 완료되면 작업이 StartupHealthCheck.StartupCompleted 속성을 true로 설정합니다.

public class StartupBackgroundService : BackgroundService
{
    private readonly StartupHealthCheck _healthCheck;

    public StartupBackgroundService(StartupHealthCheck healthCheck)
        => _healthCheck = healthCheck;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // Simulate the effect of a long-running task.
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        _healthCheck.StartupCompleted = true;
    }
}

StartupHealthCheck는 장기 실행 시작 작업의 완료를 보고하고 백그라운드 서비스에 의해 설정되는 StartupCompleted 속성을 노출합니다.

public class StartupHealthCheck : IHealthCheck
{
    private volatile bool _isReady;

    public bool StartupCompleted
    {
        get => _isReady;
        set => _isReady = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        if (StartupCompleted)
        {
            return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
        }

        return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
    }
}

상태 검사는 호스팅된 서비스와 함께 Program.csAddCheck에 등록됩니다. 호스팅된 서비스가 상태 검사에서 속성을 설정해야 하므로 상태 검사도 서비스 컨테이너에 싱글톤으로 등록됩니다.

builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();

builder.Services.AddHealthChecks()
    .AddCheck<StartupHealthCheck>(
        "Startup",
        tags: new[] { "ready" });

두 가지 상태 검사 엔드포인트를 만들려면 MapHealthChecks를 두 번 호출합니다.

app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});

app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
    Predicate = _ => false
});

앞의 예제에서는 다음과 같은 상태 검사 엔드포인트를 만듭니다.

  • 준비 상태 검사를 위해 /healthz/ready. 준비 상태 검사는 ready 태그가 지정된 상태 검사를 필터링합니다.
  • 활동성 검사를 위해 /healthz/live. 활동성 검사는 HealthCheckOptions.Predicate 대리자에서 false를 반환하여 모든 상태 검사를 필터링합니다. 상태 검사 필터링에 대한 자세한 내용은 이 문서의 상태 검사 필터링을 참조하세요.

시작 작업이 완료되기 전에는 /healthz/ready 엔드포인트가 Unhealthy 상태를 보고합니다. 시작 작업이 완료되면 이 엔드포인트는 Healthy 상태를 보고합니다. /healthz/live 엔드포인트는 모든 검사를 제외하고 모든 호출에 대해 Healthy 상태를 보고합니다.

Kubernetes 예제

별도의 준비 상태 및 활동성 검사를 사용하는 것은 Kubernetes와 같은 환경에서 유용합니다. Kubernetes에서 앱은 기본 데이터베이스 가용성 테스트와 같이 요청을 수락하기 전에 시간이 많이 걸리는 시작 작업을 실행해야 할 수도 있습니다. 별도의 검사를 사용하면 오케스트레이터가 앱이 작동하고 있지만 아직 준비가 되지 않았는지 또는 앱이 시작되지 않았는지 구분할 수 있습니다. Kubernetes의 준비 상태 및 활동성 프로브에 대한 자세한 내용은 Kubernetes 설명서의 활동성 및 준비 상태 프로브 구성을 참조하세요.

다음 예제는 Kubernetes 준비 상태 프로브 구성을 보여줍니다.

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /healthz/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

상태 검사 라이브러리 배포

상태 검사를 라이브러리로 배포하려면 다음과 같이 수행합니다.

  1. IHealthCheck 인터페이스를 독립 실행형 클래스로 구현하는 상태 검사를 기록합니다. 클래스는 DI(종속성 주입), 유형 활성화 및 명명된 옵션에 의존하여 구성 데이터에 액세스할 수 있습니다.

  2. 사용하는 앱이 Program.cs 메서드에서 호출하는 매개 변수를 사용하여 확장 메서드를 기록합니다. 생성자 매개 변수로 arg1arg2를 허용하는 다음 예제 상태 검사를 참조하세요.

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);
    

    위의 시그너처는 상태 검사가 상태 검사 프로브 논리를 처리하기 위해 사용자 지정 데이터가 필요함을 나타냅니다. 상태 검사가 확장 메서드를 사용하여 등록되면 데이터는 상태 검사 인스턴스를 만드는 데 사용된 대리자에게 제공됩니다. 다음 예제에서 호출자는 다음을 지정합니다.

    • arg1: 상태 검사를 위한 정수 데이터 요소입니다.
    • arg2: 상태 검사를 위한 문자열 인수입니다.
    • name: 선택적 상태 검사 이름입니다. null이면 기본값이 사용됩니다.
    • failureStatus: 실패 상태에 대해 보고되는 선택적 HealthStatus입니다. null인 경우 HealthStatus.Unhealthy가 사용됩니다.
    • tags: 태그의 선택적 IEnumerable<string> 컬렉션입니다.
    public static class SampleHealthCheckBuilderExtensions
    {
        private const string DefaultName = "Sample";
    
        public static IHealthChecksBuilder AddSampleHealthCheck(
            this IHealthChecksBuilder healthChecksBuilder,
            int arg1,
            string arg2,
            string? name = null,
            HealthStatus? failureStatus = null,
            IEnumerable<string>? tags = default)
        {
            return healthChecksBuilder.Add(
                new HealthCheckRegistration(
                    name ?? DefaultName,
                    _ => new SampleHealthCheckWithArgs(arg1, arg2),
                    failureStatus,
                    tags));
        }
    }
    

상태 검사 게시자

IHealthCheckPublisher가 서비스 컨테이너에 추가되면 상태 검사 시스템이 주기적으로 상태 검사를 실행하고 그 결과로 PublishAsync를 호출합니다. 이 프로세스는 각 프로세스가 상태를 결정하기 위해 주기적으로 모니터링 시스템을 호출하도록 하는 푸시 기반 상태 모니터링 시스템 시나리오에서 유용합니다.

HealthCheckPublisherOptions를 사용하여 다음을 설정할 수 있습니다.

  • Delay: 인스턴스를 실행 IHealthCheckPublisher 하기 전에 앱이 시작된 후 적용되는 초기 지연입니다. 지연은 시작 시 한 번 적용되며 이후의 반복에는 적용되지 않습니다. 기본값은 5초입니다.
  • Period: 실행 기간입니다 IHealthCheckPublisher . 기본값은 30초입니다.
  • Predicate: 기본값인 null 경우 Predicate 상태 검사 게시자 서비스는 등록된 모든 상태 검사 실행합니다. 상태 검사 하위 집합을 실행하려면 검사 세트를 필터링하는 함수를 제공합니다. 조건자는 기간마다 평가됩니다.
  • Timeout: 모든 IHealthCheckPublisher 인스턴스에 대한 상태 검사 실행하기 위한 시간 제한입니다. 시간 제한 없이 실행하려면 InfiniteTimeSpan을 사용합니다. 기본값은 30초입니다.

다음 예제에서는 상태 게시자의 레이아웃을 보여 줍니다.

public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            // ...
        }
        else
        {
            // ...
        }

        return Task.CompletedTask;
    }
}

HealthCheckPublisherOptions 클래스는 상태 검사 게시자의 동작을 구성하기 위한 속성을 제공합니다.

다음 예제에서는 상태 검사 게시자를 싱글톤으로 등록하고 HealthCheckPublisherOptions를 구성합니다.

builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});

builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();

AspNetCore.Diagnostics.HealthChecks:

개별 상태검사s

Delay 각각 PeriodHealthCheckRegistration 개별적으로 설정할 수 있습니다. 이는 설정된 HealthCheckPublisherOptions기간과 다른 속도로 일부 상태 검사 실행하려는 경우에 유용합니다.

다음 코드는 다음을 Delay 설정합니다.PeriodSampleHealthCheck1

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks()
   .Add(new HealthCheckRegistration(
       name: "SampleHealthCheck1",
       instance: new SampleHealthCheck(),
       failureStatus: null,
       tags: null,
       timeout: default)
   {
       Delay = TimeSpan.FromSeconds(40),
       Period = TimeSpan.FromSeconds(30)
   });

var app = builder.Build();

app.MapHealthChecks("/healthz");

app.Run();

종속성 주입 및 상태 검사

종속성 주입을 사용하여 상태 검사 클래스 내에서 특정 Type 인스턴스를 사용할 수 있습니다. 종속성 주입은 상태 검사에 옵션 또는 전역 구성을 삽입하는 데 유용할 수 있습니다. 종속성 주입을 사용하는 것은 상태 검사를 구성하는 일반적인 시나리오가 아닙니다. 일반적으로 각 상태 검사는 실제 테스트와 매우 관련이 있으며 IHealthChecksBuilder 확장 메서드를 사용하여 구성됩니다.

다음 예제에서는 종속성 주입을 통해 구성 개체를 검색하는 샘플 상태 검사를 보여 줍니다.

public class SampleHealthCheckWithDI : IHealthCheck
{
    private readonly SampleHealthCheckWithDiConfig _config;

    public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
        => _config = config;

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // use _config ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

SampleHealthCheckWithDiConfig 및 상태 검사를 서비스 컨테이너에 추가해야 합니다.

builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
    BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheckWithDI>(
        "With Dependency Injection",
        tags: new[] { "inject" });

UseHealthChecks 및 MapHealthChecks

호출자가 상태 검사 액세스할 수 있도록 하는 두 가지 방법이 있습니다.

  • UseHealthChecks는 미들웨어 파이프라인에서 상태 검사 요청을 처리하기 위한 미들웨어를 등록합니다.
  • MapHealthChecks는 상태 검사 엔드포인트를 등록합니다. 엔드포인트는 앱의 다른 엔드포인트와 일치하고 실행됩니다.

오버 UseHealthChecks 를 사용할 MapHealthChecks 경우의 이점은 권한 부여와 같은 엔드포인트 인식 미들웨어를 사용하고 일치 정책을 보다 세밀하게 제어할 수 있다는 점입니다. 오버 MapHealthChecks 사용 UseHealthChecks 의 주요 이점은 미들웨어 파이프라인에서 상태 검사 실행되는 위치를 정확하게 제어하는 것입니다.

UseHealthChecks:

  • 요청이 상태 검사 엔드포인트와 일치하면 파이프라인을 종료합니다. 로깅 및 기타 미들웨어와 같은 불필요한 작업을 방지하므로 단락이 바람직한 경우가 많습니다.
  • 주로 파이프라인에서 상태 검사 미들웨어를 구성하는 데 사용됩니다.
  • 포트의 경로를 비어 있거나 비어 PathString있는 null 경로와 일치시킬 수 있습니다. 지정된 포트에 대한 모든 요청에 대해 상태 검사 수행할 수 있습니다.
  • 소스 코드

MapHealthChecks 허용:

  • 요청이 상태 검사 엔드포인트와 일치하는 경우 파이프라인을 종료합니다ShortCircuit. 예들 들어 app.MapHealthChecks("/healthz").ShortCircuit();입니다. 자세한 내용은 라우팅 후 단락 미들웨어를 참조 하세요.
  • 상태 검사 대한 특정 경로 또는 엔드포인트 매핑
  • 상태 검사 엔드포인트에 액세스할 수 있는 URL 또는 경로의 사용자 지정
  • 여러 상태 검사 엔드포인트를 다른 경로 또는 구성으로 매핑합니다. 여러 엔드포인트 지원:
    • 다양한 유형의 상태 검사 또는 구성 요소에 대해 별도의 엔드포인트를 사용하도록 설정합니다.
    • 앱 상태의 다양한 측면을 구분하거나 상태 검사 하위 집합에 특정 구성을 적용하는 데 사용됩니다.
  • 소스 코드

추가 리소스

참고 항목

이 문서는 부분적으로 인공 지능의 도움을 받아 만들어졌습니다. 게시하기 전에 작성자가 필요에 따라 내용을 검토하고 수정했습니다. Microsoft Learn에서 AI로 생성된 콘텐츠를 사용하기 위한 원칙을 참조하세요.

ASP.NET Core는 앱 인프라 구성 요소의 상태를 보고하기 위해 상태 검사 미들웨어와 라이브러리를 제공합니다.

상태 검사는 앱에 의해 HTTP 엔드포인트로서 노출됩니다. 상태 검사 엔드포인트는 다양한 실시간 모니터링 시나리오에 맞게 구성할 수 있습니다.

  • 상태 프로브는 컨테이너 오케스트레이터와 부하 분산 장치가 앱 상태를 검사하는 데 사용할 수 있습니다. 예를 들어, 컨테이너 오케스트레이터는 롤링 배포를 중지하거나 컨테이너를 다시 시작하여 실패한 상태 검사에 응답할 수 있습니다. 부하 분산 장치는 장애가 발생한 상태 검사 인스턴스로부터 트래픽을 다른 곳으로 라우팅하여 비정상 앱에 대응할 수 있습니다.
  • 메모리, 디스크 및 기타 물리적 서버 리소스의 사용이 정상적인 상태인지 모니터링할 수 있습니다.
  • 상태 검사는 데이터베이스 및 외부 서비스 엔드포인트와 같은 앱 종속성을 테스트하여 가용성 및 정상 작동 여부를 확인할 수 있습니다.

샘플 코드 보기 및 다운로드(다운로드 방법)

샘플 앱에는 이 문서에 설명된 시나리오의 예제가 포함되어 있습니다. 지정된 시나리오에 대해 샘플 앱을 실행하려면 명령 셸의 프로젝트 폴더에서 dotnet run 명령을 사용합니다. 샘플 앱의 사용 방법에 대한 자세한 내용은 샘플 앱의 README.md 파일과 이 문서의 시나리오 설명을 참조하세요.

필수 조건

상태 검사는 일반적으로 외부 모니터링 서비스 또는 컨테이너 오케스트레이터와 함께 사용되어 앱 상태를 검사합니다. 앱에 상태 검사를 추가하기 전에 사용할 모니터링 시스템을 결정합니다. 모니터링 시스템은 어떤 유형의 상태 검사를 만들고 그 엔드포인트를 구성하는 방법을 지정합니다.

Microsoft.AspNetCore.Diagnostics.HealthChecks 패키지는 ASP.NET Core 앱에서 암시적으로 참조됩니다. Entity Framework Core를 사용하여 상태 검사를 수행하려면 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 패키지에 대한 참조를 추가합니다.

샘플 앱은 여러 시나리오의 상태 검사를 보여주는 시작 코드를 제공합니다. 데이터베이스 프로브 시나리오는 AspNetCore.Diagnostics.HealthChecks를 사용하여 데이터베이스 연결의 상태를 검사합니다. DbContext 프로브 시나리오는 EF CoreDbContext를 사용하여 데이터베이스를 검사합니다. 데이터베이스 시나리오를 탐색하려면 샘플 앱:

참고 항목

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

다른 상태 검사 시나리오는 관리 포트에 대해 상태 검사를 필터링하는 방법을 보여줍니다. 샘플 앱을 사용하려면 관리 URL과 관리 포트가 포함된 Properties/launchSettings.json 파일을 만들어야 합니다. 자세한 내용은 포트별 필터링 섹션을 참조하세요.

기본 상태 프로브

많은 앱의 경우, 요청을 처리할 수 있는 앱의 가용성(활동성)을 보고하는 기본 상태 검사 구성으로 앱 상태를 충분히 파악할 수 있습니다.

기본 구성은 상태 검사 서비스를 등록하고 상태 검사 미들웨어를 호출하여 URL 엔드포인트에서 상태 응답을 사용하여 응답합니다. 기본적으로 특정 종속성이나 하위 시스템을 테스트하기 위해 특정 상태 검사가 등록되지 않습니다. 앱은 상태 엔드포인트 URL에서 응답할 수 있는 경우 정상으로 간주됩니다. 기본 응답 기록기는 상태(HealthStatus)를 클라이언트에 대한 일반 텍스트 응답으로 기록하여 HealthStatus.Healthy, HealthStatus.Degraded 또는 HealthStatus.Unhealthy 상태를 나타냅니다.

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. Startup.Configure에서 MapHealthChecks를 호출하여 상태 검사 엔드포인트를 만듭니다.

샘플 앱에서 상태 검사 엔드포인트는 /health에 만들어집니다(BasicStartup.cs).

public class BasicStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHealthChecks("/health");
        });
    }
}

샘플 앱을 사용하여 기본 구성 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario basic

Docker 예

Docker는 기본 상태 검사 구성을 사용하는 앱의 상태를 검사하는 데 사용할 수 있는 기본 제공 HEALTHCHECK 지시문을 제공합니다.

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit

상태 검사 만들기

상태 검사는 IHealthCheck 인터페이스를 구현하여 만듭니다. CheckHealthAsync 메서드는 상태를 Healthy, Degraded 또는 Unhealthy로 나타내는 HealthCheckResult를 반환합니다. 결과는 구성 가능한 상태 코드가 있는 일반 텍스트 응답으로 기록됩니다(구성은 상태 검사 옵션 섹션에 설명되어 있음). HealthCheckResult는 선택 사항인 키-값 쌍을 반환할 수도 있습니다.

다음 ExampleHealthCheck 클래스는 상태 검사의 레이아웃을 보여줍니다. 상태 검사 논리는 CheckHealthAsync 메서드에 배치됩니다. 다음 예제에서는 더미 변수 healthCheckResultHealthytrue로 설정합니다. healthCheckResultHealthy 값이 false로 설정되면 HealthCheckRegistration.FailureStatus 상태가 반환됩니다.

public class ExampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var healthCheckResultHealthy = true;

        if (healthCheckResultHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(context.Registration.FailureStatus, 
            "An unhealthy result."));
    }
}

검사 중에 CheckHealthAsync가 예외를 throw하는 경우, HealthReportEntry.StatusFailureStatus로 설정된 새 HealthReportEntry가 반환됩니다. 이는 AddCheck로 정의되며(상태 검사 서비스 등록 섹션 참조) 처음에 검사가 실패한 원인이 된 내부 예외를 포함합니다. Description은 예외의 메시지로 설정됩니다.

상태 검사 서비스 등록

ExampleHealthCheck 형식은 Startup.ConfigureServicesAddCheck으로 상태 검사 서비스에 추가됩니다.

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>("example_health_check");

다음 예제에 표시된 AddCheck 오버로드는 상태 검사에서 오류가 보고되면 보고하도록 오류 상태(HealthStatus)를 설정합니다. 오류 상태가 null(기본값)로 설정되면 HealthStatus.Unhealthy가 보고됩니다. 이 오버로드는 라이브러리 작성자에게 유용한 시나리오입니다. 이 라이브러리에서는 상태 검사 구현이 설정을 준수하는 경우 상태 검사 실패가 발생할 때 라이브러리가 나타내는 오류 상태는 앱에 의해 적용됩니다.

태그를 사용하여 상태 검사를 필터링할 수 있습니다(필터 상태 검사 섹션에 자세히 설명되어 있음).

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>(
        "example_health_check",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "example" });

AddCheck는 람다 함수를 실행할 수도 있습니다. 다음 예제에서 상태 검사 이름은 Example로 지정되고 검사는 항상 정상 상태를 반환합니다.

services.AddHealthChecks()
    .AddCheck("Example", () =>
        HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });

AddTypeActivatedCheck를 호출하여 상태 검사 구현에 인수를 전달합니다. 다음 예제에서 TestHealthCheckWithArgsCheckHealthAsync가 호출될 때 사용할 정수 및 문자열을 허용합니다.

private class TestHealthCheckWithArgs : IHealthCheck
{
    public TestHealthCheckWithArgs(int i, string s)
    {
        I = i;
        S = s;
    }

    public int I { get; set; }

    public string S { get; set; }

    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, 
        CancellationToken cancellationToken = default)
    {
        ...
    }
}

TestHealthCheckWithArgs는 구현에 전달된 정수 및 문자열로 AddTypeActivatedCheck를 호출하여 등록됩니다.

services.AddHealthChecks()
    .AddTypeActivatedCheck<TestHealthCheckWithArgs>(
        "test", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "example" }, 
        args: new object[] { 5, "string" });

상태 검사 라우팅 사용

Startup.Configure에서 엔드포인트 URL 또는 상대 경로를 사용하여 엔드포인트 작성기에 MapHealthChecks를 호출합니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

호스트 필요

RequireHost를 호출하여 상태 검사 엔드포인트에 대해 허용된 호스트를 하나 이상 지정합니다. 호스트는 punycode가 아닌 유니코드여야 하고 포트를 포함할 수 있습니다. 컬렉션을 제공하지 않으면 모든 호스트가 허용됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});

자세한 내용은 포트별 필터링 섹션을 참조하세요.

권한 부여 필요

RequireAuthorization을 호출하여 상태 검사 요청 엔드포인트에서 권한 부여 미들웨어를 실행합니다. RequireAuthorization 오버로드는 하나 이상의 권한 부여 정책을 허용합니다. 정책을 제공하지 않으면 기본 권한 부여 정책이 사용됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireAuthorization();
});

원본 간 요청(CORS) 사용

브라우저에서 수동으로 상태 검사를 실행하는 것이 일반적이지는 않지만, 상태 검사 엔드포인트에 RequireCors를 호출하여 CORS 미들웨어를 사용하도록 설정할 수 있습니다. RequireCors 오버로드는 CORS 정책 작성기 대리자(CorsPolicyBuilder) 또는 정책 이름을 허용합니다. 정책을 제공하지 않으면 기본 CORS 정책이 사용됩니다. 자세한 내용은 ASP.NET Core에서 CORS(원본 간 요청) 사용을 참조하세요.

상태 검사 옵션

HealthCheckOptions는 다음과 같은 상태 검사 동작을 사용자 지정할 수 있는 기회를 제공합니다.

상태 검사 필터링

기본적으로 상태 검사 미들웨어는 등록된 모든 상태 검사를 실행합니다. 상태 검사 하위 세트를 실행하려면 Predicate 옵션에 부울 값을 반환하는 함수를 제공합니다. 다음 예제에서는 상태 검사의 Tags 속성이 foo_tag 또는 baz_tag와 일치하는 경우에만 true가 반환되는 함수의 조건문에서 태그(bar_tag)에 의해 Bar 상태 검사가 필터링됩니다.

Startup.ConfigureServices의 경우

services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });

Startup.Configure에서 Predicate는 'Bar' 상태 검사를 필터링합니다. Foo 및 Baz만 실행됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("foo_tag") ||
            check.Tags.Contains("baz_tag")
    });
});

HTTP 상태 코드 사용자 지정

ResultStatusCodes를 사용하여 상태를 HTTP 상태 코드에 매핑하는 작업을 사용자 지정할 수 있습니다. 다음 StatusCodes 할당은 미들웨어에서 사용되는 기본값입니다. 요구 사항에 맞게 상태 코드 값을 변경합니다.

Startup.Configure의 경우

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResultStatusCodes =
        {
            [HealthStatus.Healthy] = StatusCodes.Status200OK,
            [HealthStatus.Degraded] = StatusCodes.Status200OK,
            [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
        }
    });
});

캐시 헤더 표시 안 함

AllowCachingResponses는 응답 캐싱을 방지하기 위해 상태 검사 미들웨어가 HTTP 헤더를 프로브 응답에 추가할지 여부를 제어합니다. 값이 false(기본값)인 경우 미들웨어는 응답 캐싱을 방지하기 위해 Cache-Control, ExpiresPragma 헤더를 설정하거나 재정의합니다. 값이 true인 경우 미들웨어는 응답 캐시 헤더를 수정하지 않습니다.

Startup.Configure의 경우

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        AllowCachingResponses = true
    });
});

출력 사용자 지정

Startup.Configure에서 HealthCheckOptions.ResponseWriter 옵션을 응답을 쓰기 위한 대리자로 설정합니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
});

기본 대리자는 HealthReport.Status의 문자열 값을 사용하여 최소 일반 텍스트 응답을 기록합니다. 다음 사용자 지정 대리자는 사용자 지정 JSON 응답을 출력합니다.

샘플 앱의 첫 번째 예제에서는 System.Text.Json를 사용하는 방법을 보여 줍니다.

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions
    {
        Indented = true
    };

    using (var stream = new MemoryStream())
    {
        using (var writer = new Utf8JsonWriter(stream, options))
        {
            writer.WriteStartObject();
            writer.WriteString("status", result.Status.ToString());
            writer.WriteStartObject("results");
            foreach (var entry in result.Entries)
            {
                writer.WriteStartObject(entry.Key);
                writer.WriteString("status", entry.Value.Status.ToString());
                writer.WriteString("description", entry.Value.Description);
                writer.WriteStartObject("data");
                foreach (var item in entry.Value.Data)
                {
                    writer.WritePropertyName(item.Key);
                    JsonSerializer.Serialize(
                        writer, item.Value, item.Value?.GetType() ??
                        typeof(object));
                }
                writer.WriteEndObject();
                writer.WriteEndObject();
            }
            writer.WriteEndObject();
            writer.WriteEndObject();
        }

        var json = Encoding.UTF8.GetString(stream.ToArray());

        return context.Response.WriteAsync(json);
    }
}

두 번째 예제에서는 Newtonsoft.Json을 사용하는 방법을 보여 줍니다.

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));

    return context.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

샘플 앱에서 Newtonsoft.Json 버전의 WriteResponse를 사용할 수 있도록 CustomWriterStartup.csSYSTEM_TEXT_JSON전처리기 지시문을 주석으로 처리합니다.

상태 검사 API는 사용자가 선택한 모니터링 시스템에만 적용되는 형식이므로 복합 JSON 반환 형식에 대한 기본 제공 지원을 제공하지 않습니다. 앞의 예제에서 응답을 필요에 따라 사용자 지정합니다. System.Text.Json을 사용한 JSON 직렬화에 대한 자세한 내용은 .NET에서 JSON을 직렬화 및 역직렬화하는 방법을 참조하세요.

데이터베이스 프로브

상태 검사는 데이터베이스 쿼리를 지정하여 데이터베이스가 정상적으로 응답하는지를 나타내기 위해 부울 테스트로서 실행할 수 있습니다.

샘플 앱은 ASP.NET Core 앱의 상태 검사 라이브러리인 AspNetCore.Diagnostics.HealthChecks를 사용하여 SQL Server 데이터베이스에 대한 상태 검사를 실행합니다. AspNetCore.Diagnostics.HealthChecks는 데이터베이스에 연결이 양호한지 확인하기 위해 데이터베이스에 대해 SELECT 1 쿼리를 실행합니다.

Warning

쿼리로 데이터베이스 연결을 검사할 때 신속하게 반환되는 쿼리를 선택합니다. 쿼리 방식 실행은 데이터베이스의 오버로드와 성능 저하를 유발할 수 있습니다. 대부분의 경우 테스트 쿼리를 실행할 필요가 없습니다. 간단히 데이터베이스에 연결하는 정도로도 충분합니다. 쿼리를 실행해야 하는 경우 SELECT 1과 같은 간단한 SELECT 쿼리를 선택합니다.

AspNetCore.HealthChecks.SqlServer에 대한 패키지 참조를 포함합니다.

샘플 앱의 appsettings.json 파일에서 유효한 데이터베이스 연결 문자열을 제공합니다. 앱은 HealthCheckSample이라고 하는 SQL Server 데이터베이스를 사용합니다.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "IncludeScopes": "true"
    }
  },
  "AllowedHosts": "*"
}

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. 샘플 앱은 데이터베이스의 연결 문자열(DbHealthStartup.cs)를 사용하여 메서드를 호출 AddSqlServer 합니다.

services.AddHealthChecks()
    .AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

샘플 앱을 사용하여 데이터베이스 프로브 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario db

참고 항목

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

Entity Framework Core DbContext 프로브

DbContext 검사는 앱이 EF CoreDbContext에 대해 구성된 데이터베이스와 통신할 수 있음을 확인합니다. DbContext 검사는 다음과 같은 앱에서 지원됩니다.

AddDbContextCheck<TContext>DbContext에 대한 상태 검사를 등록합니다. DbContext는 메서드에 TContext로 제공됩니다. 오버로드는 오류 상태, 태그 및 사용자 지정 테스트 쿼리를 구성할 수 있습니다.

기본적으로:

  • DbContextHealthCheck는 EF Core의 CanConnectAsync 메서드를 호출합니다. AddDbContextCheck 메서드 오버로드를 사용하여 상태를 검사할 때 실행되는 작업을 사용자 정의할 수 있습니다.
  • 상태 검사의 이름은 TContext 형식의 이름입니다.

샘플 앱에서 AppDbContextAddDbContextCheck에 제공되고 Startup.ConfigureServices의 서비스로 등록됩니다(DbContextHealthStartup.cs).

services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>();

services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(
        Configuration["ConnectionStrings:DefaultConnection"]);
});

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

샘플 앱을 사용하여 DbContext 프로브 시나리오를 실행하려면 연결 문자열로 지정된 데이터베이스가 SQL Server 인스턴스에 있지 않은지 확인합니다. 데이터베이스가 있으면 삭제합니다.

명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario dbcontext

앱을 실행한 후 브라우저의 /health 엔드포인트에 요청하여 상태를 검사합니다. 데이터베이스 및 AppDbContext가 존재하기 않기 때문에 앱은 다음 응답을 제공합니다.

Unhealthy

데이터베이스를 만드는 샘플 앱을 트리거합니다. /createdatabase에 요청합니다. 앱은 다음과 같이 응답합니다.

Creating the database...
Done!
Navigate to /health to see the health status.

/health 엔드포인트에 요청합니다. 데이터베이스와 컨텍스트가 존재하기 때문에 앱은 다음과 같이 응답합니다.

Healthy

데이터베이스를 삭제하는 샘플 앱을 트리거합니다. /deletedatabase에 요청합니다. 앱은 다음과 같이 응답합니다.

Deleting the database...
Done!
Navigate to /health to see the health status.

/health 엔드포인트에 요청합니다. 앱은 다음과 같이 비정상 응답을 제공합니다.

Unhealthy

별도의 준비 상태 및 활동성 프로브

일부 호스팅 시나리오에서 두 가지 앱 상태를 구분하는 한 쌍의 상태 검사가 사용됩니다.

  • ‘준비 상태’는 앱이 정상적으로 실행 중이지만 요청을 받을 준비가 되지 않았음을 나타냅니다.
  • ‘활동성’은 앱의 작동이 중단되어 다시 시작해야 함을 나타냅니다.

다음 예제를 고려하세요. 앱은 요청을 처리할 준비가 되기 전에 큰 구성 파일을 다운로드해야 합니다. 앱에서 파일 다운로드를 여러 번 다시 시도할 수 있으므로 초기 다운로드가 실패하더라도 앱을 다시 시작하지 않는 것이 좋습니다. 활동성 프로브를 사용하여 프로세스의 활동성을 설명하며 다른 검사를 실행하지 않습니다. 또한 구성 파일이 다운로드되기 전에는 앱에 요청을 보내지 못하게 합니다. ‘준비 상태 프로브’를 사용하여 다운로드에 성공하여 앱이 요청을 받을 준비가 될 때까지 “준비되지 않음” 상태를 표시합니다.

샘플 앱에는 호스팅된 서비스에서 장기 실행 시작 작업 완료를 보고하는 상태 검사가 있습니다. 호스트 StartupHostedServiceHealthCheck 된 서비스가 장기 실행 작업이 완료된 시점으로 true 설정할 수 있는 속성을 StartupTaskCompleted노출합니다()StartupHostedServiceHealthCheck.cs.

public class StartupHostedServiceHealthCheck : IHealthCheck
{
    private volatile bool _startupTaskCompleted = false;

    public string Name => "slow_dependency_check";

    public bool StartupTaskCompleted
    {
        get => _startupTaskCompleted;
        set => _startupTaskCompleted = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        if (StartupTaskCompleted)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The startup task is finished."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The startup task is still running."));
    }
}

장기 실행 백그라운드 작업은 호스팅된 서비스(Services/StartupHostedService)에 의해 시작됩니다. 작업이 끝나면 StartupHostedServiceHealthCheck.StartupTaskCompletedtrue로 설정됩니다.

public class StartupHostedService : IHostedService, IDisposable
{
    private readonly int _delaySeconds = 15;
    private readonly ILogger _logger;
    private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

    public StartupHostedService(ILogger<StartupHostedService> logger,
        StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
    {
        _logger = logger;
        _startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is starting.");

        // Simulate the effect of a long-running startup task.
        Task.Run(async () =>
        {
            await Task.Delay(_delaySeconds * 1000);

            _startupHostedServiceHealthCheck.StartupTaskCompleted = true;

            _logger.LogInformation("Startup Background Service has started.");
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is stopping.");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

상태 검사는 호스팅된 서비스와 함께 Startup.ConfigureServicesAddCheck에 등록됩니다. 호스트된 서비스는 상태 검사 속성을 설정해야 하므로 상태 검사 서비스 컨테이너(LivenessProbeStartup.cs)에도 등록됩니다.

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다. 샘플 앱에서 상태 검사 엔드포인트는 다음 위치에 만들어집니다.

  • 준비 상태 검사를 위해 /health/ready. 준비 상태 검사는 ready 태그가 있는 상태 검사에서 상태 검사를 필터링합니다.
  • 활동성 검사를 위해 /health/live. 활동성 검사는 HealthCheckOptions.Predicate에서 false를 반환하여 StartupHostedServiceHealthCheck를 필터링합니다(자세한 내용은 상태 검사 필터링에서 참조).

다음 예제 코드에서:

  • 준비 상태 검사는 'ready' 태그가 있는 등록된 검사를 모두 사용합니다.
  • Predicate는 모든 검사를 제외하고 200-Ok를 반환합니다.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

샘플 앱을 사용하여 준비 상태/활동성 구성 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario liveness

브라우저에서 15초가 경과할 때까지 /health/ready를 여러 번 방문합니다. 상태 검사는 첫 15초 동안 Unhealthy를 보고합니다. 15초 후, 엔드포인트는 Healthy를 보고하여 호스팅된 서비스에 의해 장기 실행 작업이 완료되었음을 나타냅니다.

이 예제에서는 2초 지연을 사용하여 첫 번째 준비 검사를 실행하는 상태 검사 게시자(IHealthCheckPublisher 구현)도 만듭니다. 자세한 내용은 상태 검사 게시자 섹션을 참조하세요.

Kubernetes 예제

별도의 준비 상태 및 활동성 검사를 사용하는 것은 Kubernetes와 같은 환경에서 유용합니다. Kubernetes에서 앱은 기본 데이터베이스 가용성 테스트와 같이 요청을 수락하기 전에 시간이 많이 걸리는 시작 작업을 실행해야 할 수도 있습니다. 별도의 검사를 사용하면 오케스트레이터가 앱이 작동하고 있지만 아직 준비가 되지 않았는지 또는 앱이 시작되지 않았는지 구분할 수 있습니다. Kubernetes의 준비 상태 및 활동성 프로브에 대한 자세한 내용은 Kubernetes 설명서의 활동성 및 준비 상태 프로브 구성을 참조하세요.

다음 예제는 Kubernetes 준비 상태 프로브 구성을 보여줍니다.

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /health/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

사용자 지정 응답 기록기가 있는 메트릭 기반 프로브

샘플 앱은 사용자 지정 응답 기록기가 있는 메모리 상태를 보여줍니다.

앱이 일정한 메모리 임계값(샘플 앱의 경우 1GB)을 초과하여 사용하는 경우 MemoryHealthCheck는 성능이 저하된 상태를 보고합니다. HealthCheckResult에는 앱의 가비지 수집기(GC) 정보가 포함됩니다(MemoryHealthCheck.cs).

public class MemoryHealthCheck : IHealthCheck
{
    private readonly IOptionsMonitor<MemoryCheckOptions> _options;

    public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
    {
        _options = options;
    }

    public string Name => "memory_check";

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var options = _options.Get(context.Registration.Name);

        // Include GC information in the reported diagnostics.
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };
        var status = (allocated < options.Threshold) ?
            HealthStatus.Healthy : context.Registration.FailureStatus;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: "Reports degraded status if allocated bytes " +
                $">= {options.Threshold} bytes.",
            exception: null,
            data: data));
    }
}

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. AddCheck에 전달하여 상태 검사를 사용하는 대신 MemoryHealthCheck는 서비스로 등록됩니다. 모든 IHealthCheck 등록된 서비스는 상태 검사 서비스 및 미들웨어에 사용할 수 있습니다. 상태 확인 서비스를 Singleton 서비스로 등록하는 것이 좋습니다.

CustomWriterStartup.cs 샘플 앱에서 다음을 수행합니다.

services.AddHealthChecks()
    .AddMemoryHealthCheck("memory");

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다. 상태 검사가 실행될 때 사용자 정의 JSON 응답을 출력하기 위해 ResponseWriter 속성에 WriteResponse 대리자가 제공됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
}

WriteResponse 대리자는 CompositeHealthCheckResult를 JSON 객체로 형식 지정하고 상태 검사 응답을 위해 JSON 출력을 생성합니다. 자세한 내용은 출력 사용자 지정 섹션을 참조하세요.

샘플 앱을 사용하여 사용자 지정 응답 기록기 출력으로 메트릭 기반 프로브를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario writer

참고 항목

AspNetCore.Diagnostics.HealthChecks에는 디스크 스토리지 및 최댓값 활동성 검사를 포함하여 메트릭 기반 상태 확인 시나리오가 포함됩니다.

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

포트별 필터링

지정된 포트에 대한 상태 검사 요청을 제한하는 포트를 지정하는 URL 패턴을 사용하여 MapHealthChecksRequireHost를 호출합니다. 이 방법은 일반적으로 컨테이너 환경에서 서비스 모니터링을 위해 포트를 노출하는 데 사용됩니다.

샘플 앱은 환경 변수 구성 공급자를 사용하여 포트를 구성합니다. 포트는 launchSettings.json 파일에서 설정되고 환경 변수를 통해 구성 공급자에게 전달됩니다. 또한 관리 포트에서 요청을 수신하도록 서버를 구성해야 합니다.

샘플 앱을 사용하여 관리 포트 구성을 보여 주려면 폴더에 launchSettings.jsonProperties 파일을 만듭니다.

다음 Properties/launchSettings.json 파일은 샘플 앱의 프로젝트 파일에 포함되지 않으며 수동으로 만들어야 합니다.

{
  "profiles": {
    "SampleApp": {
      "commandName": "Project",
      "commandLineArgs": "",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
        "ASPNETCORE_MANAGEMENTPORT": "5001"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. Startup.Configure에서 MapHealthChecks를 호출하여 상태 검사 엔드포인트를 만듭니다.

샘플 앱에서 Startup.Configure의 엔드포인트에 대한 RequireHost 호출은 구성의 관리 포트를 지정합니다.

endpoints.MapHealthChecks("/health")
    .RequireHost($"*:{Configuration["ManagementPort"]}");

샘플 앱에서 엔드포인트는 Startup.Configure에서 만들어집니다. 다음 예제 코드에서:

  • 준비 상태 검사는 'ready' 태그가 있는 등록된 검사를 모두 사용합니다.
  • Predicate는 모든 검사를 제외하고 200-Ok를 반환합니다.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

참고 항목

코드에서 관리 포트를 명시적으로 설정하여 샘플 앱에 launchSettings.json 파일을 만들지 않도록 할 수 있습니다. Program.cs 생성되는 위치에서 HostBuilder 호출을 ListenAnyIP 추가하고 앱의 관리 포트 엔드포인트를 제공합니다. ManagementPortStartup.csConfigure에서 RequireHost로 관리 포트를 지정합니다.

Program.cs:

return new HostBuilder()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseKestrel()
            .ConfigureKestrel(serverOptions =>
            {
                serverOptions.ListenAnyIP(5001);
            })
            .UseStartup(startupType);
    })
    .Build();

ManagementPortStartup.cs:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});

샘플 앱을 사용하여 관리 포트 구성 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario port

상태 검사 라이브러리 배포

상태 검사를 라이브러리로 배포하려면 다음과 같이 수행합니다.

  1. IHealthCheck 인터페이스를 독립 실행형 클래스로 구현하는 상태 검사를 기록합니다. 클래스는 DI(종속성 주입), 유형 활성화 및 명명된 옵션에 의존하여 구성 데이터에 액세스할 수 있습니다.

    CheckHealthAsync의 상태 검사 논리에서:

    • data1data2는 메서드에서 프로브의 상태 검사 논리를 실행하는 데 사용됩니다.
    • AccessViolationException이 처리됩니다.

    AccessViolationException이 발생하는 경우 사용자가 상태 검사 실패 상태를 구성할 수 있도록 FailureStatusHealthCheckResult와 함께 반환됩니다.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    namespace SampleApp
    {
        public class ExampleHealthCheck : IHealthCheck
        {
            private readonly string _data1;
            private readonly int? _data2;
    
            public ExampleHealthCheck(string data1, int? data2)
            {
                _data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
                _data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
            }
    
            public async Task<HealthCheckResult> CheckHealthAsync(
                HealthCheckContext context, CancellationToken cancellationToken)
            {
                try
                {
                    return HealthCheckResult.Healthy();
                }
                catch (AccessViolationException ex)
                {
                    return new HealthCheckResult(
                        context.Registration.FailureStatus,
                        description: "An access violation occurred during the check.",
                        exception: ex,
                        data: null);
                }
            }
        }
    }
    
  2. 사용하는 앱이 Startup.Configure 메서드에서 호출하는 매개 변수를 사용하여 확장 메서드를 기록합니다. 다음 예제에서는 다음 상태 검사 메서드 서명을 가정합니다.

    ExampleHealthCheck(string, string, int )
    

    이전 서명은 ExampleHealthCheck가 상태 검사 프로브 로직을 처리하기 위해 추가 데이터가 필요함을 나타냅니다. 상태 검사가 확장 메서드를 사용하여 등록되면 데이터는 상태 검사 인스턴스를 만드는 데 사용된 대리자에게 제공됩니다. 다음 예제에서 호출자는 선택 사항을 지정합니다.

    • 상태 검사 이름(name). null인 경우 example_health_check가 사용됩니다.
    • 상태 검사를 위한 문자열 데이터 요소입니다(data1).
    • 상태 검사를 위한 정수 데이터 요소입니다(data2). null인 경우 1가 사용됩니다.
    • 실패 상태입니다(HealthStatus). 기본값은 null입니다. null인 경우 HealthStatus.Unhealthy는 오류 상태에 대해 보고됩니다.
    • 태그(IEnumerable<string>)입니다.
    using System.Collections.Generic;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public static class ExampleHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddExampleHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            string data1,
            int data2 = 1,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ExampleHealthCheck(data1, data2),
                failureStatus,
                tags));
        }
    }
    

상태 검사 게시자

IHealthCheckPublisher가 서비스 컨테이너에 추가되면 상태 검사 시스템이 주기적으로 상태 검사를 실행하고 그 결과로 PublishAsync를 호출합니다. 이는 각 프로세스가 상태를 결정하기 위해 주기적으로 모니터링 시스템을 호출하도록 하는 푸시 기반 상태 모니터링 시스템 시나리오에서 유용합니다.

IHealthCheckPublisher 인터페이스는 단일 메서드를 가집니다.

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions를 사용하여 다음을 설정할 수 있습니다.

  • Delay: 인스턴스를 실행 IHealthCheckPublisher 하기 전에 앱이 시작된 후 적용되는 초기 지연입니다. 지연은 시작 시 한 번 적용되며 후속 반복에는 적용되지 않습니다. 기본값은 5초입니다.
  • Period: 실행 기간입니다 IHealthCheckPublisher . 기본값은 30초입니다.
  • Predicate: 기본값인 null 경우 Predicate 상태 검사 게시자 서비스는 등록된 모든 상태 검사 실행합니다. 상태 검사 하위 집합을 실행하려면 검사 세트를 필터링하는 함수를 제공합니다. 조건자는 기간마다 평가됩니다.
  • Timeout: 모든 IHealthCheckPublisher 인스턴스에 대한 상태 검사 실행하기 위한 시간 제한입니다. 시간 제한 없이 실행하려면 InfiniteTimeSpan을 사용합니다. 기본값은 30초입니다.

샘플 앱에서 ReadinessPublisherIHealthCheckPublisher 구현입니다. 상태 검사 상태는 다음의 로그 수준에서 각 검사에 대해 기록됩니다.

public class ReadinessPublisher : IHealthCheckPublisher
{
    private readonly ILogger _logger;

    public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
    {
        _logger = logger;
    }

    // The following example is for demonstration purposes only. Health Checks
    // Middleware already logs health checks results. A real-world readiness
    // check in a production app might perform a set of more expensive or
    // time-consuming checks to determine if other resources are responding
    // properly.
    public Task PublishAsync(HealthReport report,
        CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            _logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }
        else
        {
            _logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }

        cancellationToken.ThrowIfCancellationRequested();

        return Task.CompletedTask;
    }
}

샘플 앱의 LivenessProbeStartup 예제에서 StartupHostedService 준비 검사에는 2초 시작 지연이 있고 30초마다 검사가 실행됩니다. IHealthCheckPublisher 구현을 활성화하기 위해 샘플은 DI(종속성 주입) 컨테이너에서 ReadinessPublisher를 싱글톤 서비스로 등록합니다.

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

참고 항목

AspNetCore.Diagnostics.HealthChecks에는 Application Insights를 포함하여 몇몇 시스템에 대한 게시자를 포함합니다.

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

MapWhen으로 상태 검사 제한

MapWhen을 사용하여 상태 검사 엔드포인트에 대한 요청 파이프라인을 조건부로 분기합니다.

다음 예제에서 MapWhenapi/HealthCheck 엔드포인트에 대한 GET 요청을 받는 경우 상태 검사 미들웨어를 활성화하도록 요청 파이프라인을 분기합니다.

app.MapWhen(
    context => context.Request.Method == HttpMethod.Get.Method && 
        context.Request.Path.StartsWith("/api/HealthCheck"),
    builder => builder.UseHealthChecks());

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});

자세한 내용은 ASP.NET Core 미들웨어를 참조하세요.

ASP.NET Core는 앱 인프라 구성 요소의 상태를 보고하기 위해 상태 검사 미들웨어와 라이브러리를 제공합니다.

상태 검사는 앱에 의해 HTTP 엔드포인트로서 노출됩니다. 상태 검사 엔드포인트는 다양한 실시간 모니터링 시나리오에 맞게 구성할 수 있습니다.

  • 상태 프로브는 컨테이너 오케스트레이터와 부하 분산 장치가 앱 상태를 검사하는 데 사용할 수 있습니다. 예를 들어, 컨테이너 오케스트레이터는 롤링 배포를 중지하거나 컨테이너를 다시 시작하여 실패한 상태 검사에 응답할 수 있습니다. 부하 분산 장치는 장애가 발생한 상태 검사 인스턴스로부터 트래픽을 다른 곳으로 라우팅하여 비정상 앱에 대응할 수 있습니다.
  • 메모리, 디스크 및 기타 물리적 서버 리소스의 사용이 정상적인 상태인지 모니터링할 수 있습니다.
  • 상태 검사는 데이터베이스 및 외부 서비스 엔드포인트와 같은 앱 종속성을 테스트하여 가용성 및 정상 작동 여부를 확인할 수 있습니다.

샘플 코드 보기 및 다운로드(다운로드 방법)

샘플 앱에는 이 문서에 설명된 시나리오의 예제가 포함되어 있습니다. 지정된 시나리오에 대해 샘플 앱을 실행하려면 명령 셸의 프로젝트 폴더에서 dotnet run 명령을 사용합니다. 샘플 앱의 사용 방법에 대한 자세한 내용은 샘플 앱의 README.md 파일과 이 문서의 시나리오 설명을 참조하세요.

필수 조건

상태 검사는 일반적으로 외부 모니터링 서비스 또는 컨테이너 오케스트레이터와 함께 사용되어 앱 상태를 검사합니다. 앱에 상태 검사를 추가하기 전에 사용할 모니터링 시스템을 결정합니다. 모니터링 시스템은 어떤 유형의 상태 검사를 만들고 그 엔드포인트를 구성하는 방법을 지정합니다.

Microsoft.AspNetCore.Diagnostics.HealthChecks 패키지는 ASP.NET Core 앱에서 암시적으로 참조됩니다. Entity Framework Core를 사용하여 상태 검사를 실행하려면 Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore 패키지에 대한 패키지 참조를 추가합니다.

샘플 앱은 여러 시나리오의 상태 검사를 보여주는 시작 코드를 제공합니다. 데이터베이스 프로브 시나리오는 AspNetCore.Diagnostics.HealthChecks를 사용하여 데이터베이스 연결의 상태를 검사합니다. DbContext 프로브 시나리오는 EF CoreDbContext를 사용하여 데이터베이스를 검사합니다. 데이터베이스 시나리오를 탐색하려면 샘플 앱:

참고 항목

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

다른 상태 검사 시나리오는 관리 포트에 대해 상태 검사를 필터링하는 방법을 보여줍니다. 샘플 앱을 사용하려면 관리 URL과 관리 포트가 포함된 Properties/launchSettings.json 파일을 만들어야 합니다. 자세한 내용은 포트별 필터링 섹션을 참조하세요.

기본 상태 프로브

많은 앱의 경우, 요청을 처리할 수 있는 앱의 가용성(활동성)을 보고하는 기본 상태 검사 구성으로 앱 상태를 충분히 파악할 수 있습니다.

기본 구성은 상태 검사 서비스를 등록하고 상태 검사 미들웨어를 호출하여 URL 엔드포인트에서 상태 응답을 사용하여 응답합니다. 기본적으로 특정 종속성이나 하위 시스템을 테스트하기 위해 특정 상태 검사가 등록되지 않습니다. 앱은 상태 엔드포인트 URL에서 응답할 수 있는 경우 정상으로 간주됩니다. 기본 응답 기록기는 상태(HealthStatus)를 클라이언트에 대한 일반 텍스트 응답으로 기록하여 HealthStatus.Healthy, HealthStatus.Degraded 또는 HealthStatus.Unhealthy 상태를 나타냅니다.

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. Startup.Configure에서 MapHealthChecks를 호출하여 상태 검사 엔드포인트를 만듭니다.

샘플 앱에서 상태 검사 엔드포인트는 /health에 만들어집니다(BasicStartup.cs).

public class BasicStartup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHealthChecks();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapHealthChecks("/health");
        });
    }
}

샘플 앱을 사용하여 기본 구성 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario basic

Docker 예

Docker는 기본 상태 검사 구성을 사용하는 앱의 상태를 검사하는 데 사용할 수 있는 기본 제공 HEALTHCHECK 지시문을 제공합니다.

HEALTHCHECK CMD curl --fail http://localhost:5000/health || exit

상태 검사 만들기

상태 검사는 IHealthCheck 인터페이스를 구현하여 만듭니다. CheckHealthAsync 메서드는 상태를 Healthy, Degraded 또는 Unhealthy로 나타내는 HealthCheckResult를 반환합니다. 결과는 구성 가능한 상태 코드가 있는 일반 텍스트 응답으로 기록됩니다(구성은 상태 검사 옵션 섹션에 설명되어 있음). HealthCheckResult는 선택 사항인 키-값 쌍을 반환할 수도 있습니다.

다음 ExampleHealthCheck 클래스는 상태 검사의 레이아웃을 보여줍니다. 상태 검사 논리는 CheckHealthAsync 메서드에 배치됩니다. 다음 예제에서는 더미 변수 healthCheckResultHealthytrue로 설정합니다. healthCheckResultHealthy 값이 false로 설정되면 HealthCheckResult.Unhealthy 상태가 반환됩니다.

public class ExampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var healthCheckResultHealthy = true;

        if (healthCheckResultHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("An unhealthy result."));
    }
}

상태 검사 서비스 등록

ExampleHealthCheck 형식은 Startup.ConfigureServicesAddCheck으로 상태 검사 서비스에 추가됩니다.

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>("example_health_check");

다음 예제에 표시된 AddCheck 오버로드는 상태 검사에서 오류가 보고되면 보고하도록 오류 상태(HealthStatus)를 설정합니다. 오류 상태가 null(기본값)로 설정되면 HealthStatus.Unhealthy가 보고됩니다. 이 오버로드는 라이브러리 작성자에게 유용한 시나리오입니다. 이 라이브러리에서는 상태 검사 구현이 설정을 준수하는 경우 상태 검사 실패가 발생할 때 라이브러리가 나타내는 오류 상태는 앱에 의해 적용됩니다.

태그를 사용하여 상태 검사를 필터링할 수 있습니다(필터 상태 검사 섹션에 자세히 설명되어 있음).

services.AddHealthChecks()
    .AddCheck<ExampleHealthCheck>(
        "example_health_check",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "example" });

AddCheck는 람다 함수를 실행할 수도 있습니다. 다음 예제에서 상태 검사 이름은 Example로 지정되고 검사는 항상 정상 상태를 반환합니다.

services.AddHealthChecks()
    .AddCheck("Example", () =>
        HealthCheckResult.Healthy("Example is OK!"), tags: new[] { "example" });

AddTypeActivatedCheck를 호출하여 상태 검사 구현에 인수를 전달합니다. 다음 예제에서 TestHealthCheckWithArgsCheckHealthAsync가 호출될 때 사용할 정수 및 문자열을 허용합니다.

private class TestHealthCheckWithArgs : IHealthCheck
{
    public TestHealthCheckWithArgs(int i, string s)
    {
        I = i;
        S = s;
    }

    public int I { get; set; }

    public string S { get; set; }

    public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, 
        CancellationToken cancellationToken = default)
    {
        ...
    }
}

TestHealthCheckWithArgs는 구현에 전달된 정수 및 문자열로 AddTypeActivatedCheck를 호출하여 등록됩니다.

services.AddHealthChecks()
    .AddTypeActivatedCheck<TestHealthCheckWithArgs>(
        "test", 
        failureStatus: HealthStatus.Degraded, 
        tags: new[] { "example" }, 
        args: new object[] { 5, "string" });

상태 검사 라우팅 사용

Startup.Configure에서 엔드포인트 URL 또는 상대 경로를 사용하여 엔드포인트 작성기에 MapHealthChecks를 호출합니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
});

호스트 필요

RequireHost를 호출하여 상태 검사 엔드포인트에 대해 허용된 호스트를 하나 이상 지정합니다. 호스트는 punycode가 아닌 유니코드여야 하고 포트를 포함할 수 있습니다. 컬렉션을 제공하지 않으면 모든 호스트가 허용됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("www.contoso.com:5001");
});

자세한 내용은 포트별 필터링 섹션을 참조하세요.

권한 부여 필요

RequireAuthorization을 호출하여 상태 검사 요청 엔드포인트에서 권한 부여 미들웨어를 실행합니다. RequireAuthorization 오버로드는 하나 이상의 권한 부여 정책을 허용합니다. 정책을 제공하지 않으면 기본 권한 부여 정책이 사용됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireAuthorization();
});

원본 간 요청(CORS) 사용

브라우저에서 수동으로 상태 검사를 실행하는 것이 일반적이지는 않지만, 상태 검사 엔드포인트에 RequireCors를 호출하여 CORS 미들웨어를 사용하도록 설정할 수 있습니다. RequireCors 오버로드는 CORS 정책 작성기 대리자(CorsPolicyBuilder) 또는 정책 이름을 허용합니다. 정책을 제공하지 않으면 기본 CORS 정책이 사용됩니다. 자세한 내용은 ASP.NET Core에서 CORS(원본 간 요청) 사용을 참조하세요.

상태 검사 옵션

HealthCheckOptions는 다음과 같은 상태 검사 동작을 사용자 지정할 수 있는 기회를 제공합니다.

상태 검사 필터링

기본적으로 상태 검사 미들웨어는 등록된 모든 상태 검사를 실행합니다. 상태 검사 하위 세트를 실행하려면 Predicate 옵션에 부울 값을 반환하는 함수를 제공합니다. 다음 예제에서는 상태 검사의 Tags 속성이 foo_tag 또는 baz_tag와 일치하는 경우에만 true가 반환되는 함수의 조건문에서 태그(bar_tag)에 의해 Bar 상태 검사가 필터링됩니다.

Startup.ConfigureServices의 경우

services.AddHealthChecks()
    .AddCheck("Foo", () =>
        HealthCheckResult.Healthy("Foo is OK!"), tags: new[] { "foo_tag" })
    .AddCheck("Bar", () =>
        HealthCheckResult.Unhealthy("Bar is unhealthy!"), tags: new[] { "bar_tag" })
    .AddCheck("Baz", () =>
        HealthCheckResult.Healthy("Baz is OK!"), tags: new[] { "baz_tag" });

Startup.Configure에서 Predicate는 'Bar' 상태 검사를 필터링합니다. Foo 및 Baz만 실행됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("foo_tag") ||
            check.Tags.Contains("baz_tag")
    });
});

HTTP 상태 코드 사용자 지정

ResultStatusCodes를 사용하여 상태를 HTTP 상태 코드에 매핑하는 작업을 사용자 지정할 수 있습니다. 다음 StatusCodes 할당은 미들웨어에서 사용되는 기본값입니다. 요구 사항에 맞게 상태 코드 값을 변경합니다.

Startup.Configure의 경우

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResultStatusCodes =
        {
            [HealthStatus.Healthy] = StatusCodes.Status200OK,
            [HealthStatus.Degraded] = StatusCodes.Status200OK,
            [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
        }
    });
});

캐시 헤더 표시 안 함

AllowCachingResponses는 응답 캐싱을 방지하기 위해 상태 검사 미들웨어가 HTTP 헤더를 프로브 응답에 추가할지 여부를 제어합니다. 값이 false(기본값)인 경우 미들웨어는 응답 캐싱을 방지하기 위해 Cache-Control, ExpiresPragma 헤더를 설정하거나 재정의합니다. 값이 true인 경우 미들웨어는 응답 캐시 헤더를 수정하지 않습니다.

Startup.Configure의 경우

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        AllowCachingResponses = true
    });
});

출력 사용자 지정

Startup.Configure에서 HealthCheckOptions.ResponseWriter 옵션을 응답을 쓰기 위한 대리자로 설정합니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
});

기본 대리자는 HealthReport.Status의 문자열 값을 사용하여 최소 일반 텍스트 응답을 기록합니다. 다음 사용자 지정 대리자는 사용자 지정 JSON 응답을 출력합니다.

샘플 앱의 첫 번째 예제에서는 System.Text.Json를 사용하는 방법을 보여 줍니다.

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions
    {
        Indented = true
    };

    using (var stream = new MemoryStream())
    {
        using (var writer = new Utf8JsonWriter(stream, options))
        {
            writer.WriteStartObject();
            writer.WriteString("status", result.Status.ToString());
            writer.WriteStartObject("results");
            foreach (var entry in result.Entries)
            {
                writer.WriteStartObject(entry.Key);
                writer.WriteString("status", entry.Value.Status.ToString());
                writer.WriteString("description", entry.Value.Description);
                writer.WriteStartObject("data");
                foreach (var item in entry.Value.Data)
                {
                    writer.WritePropertyName(item.Key);
                    JsonSerializer.Serialize(
                        writer, item.Value, item.Value?.GetType() ??
                        typeof(object));
                }
                writer.WriteEndObject();
                writer.WriteEndObject();
            }
            writer.WriteEndObject();
            writer.WriteEndObject();
        }

        var json = Encoding.UTF8.GetString(stream.ToArray());

        return context.Response.WriteAsync(json);
    }
}

두 번째 예제에서는 Newtonsoft.json을 사용하는 방법을 보여 줍니다.

private static Task WriteResponse(HttpContext context, HealthReport result)
{
    context.Response.ContentType = "application/json";

    var json = new JObject(
        new JProperty("status", result.Status.ToString()),
        new JProperty("results", new JObject(result.Entries.Select(pair =>
            new JProperty(pair.Key, new JObject(
                new JProperty("status", pair.Value.Status.ToString()),
                new JProperty("description", pair.Value.Description),
                new JProperty("data", new JObject(pair.Value.Data.Select(
                    p => new JProperty(p.Key, p.Value))))))))));

    return context.Response.WriteAsync(
        json.ToString(Formatting.Indented));
}

샘플 앱에서 Newtonsoft.Json 버전의 WriteResponse를 사용할 수 있도록 CustomWriterStartup.csSYSTEM_TEXT_JSON전처리기 지시문을 주석으로 처리합니다.

상태 검사 API는 사용자가 선택한 모니터링 시스템에만 적용되는 형식이므로 복합 JSON 반환 형식에 대한 기본 제공 지원을 제공하지 않습니다. 앞의 예제에서 응답을 필요에 따라 사용자 지정합니다. System.Text.Json을 사용한 JSON 직렬화에 대한 자세한 내용은 .NET에서 JSON을 직렬화 및 역직렬화하는 방법을 참조하세요.

데이터베이스 프로브

상태 검사는 데이터베이스 쿼리를 지정하여 데이터베이스가 정상적으로 응답하는지를 나타내기 위해 부울 테스트로서 실행할 수 있습니다.

샘플 앱은 ASP.NET Core 앱의 상태 검사 라이브러리인 AspNetCore.Diagnostics.HealthChecks를 사용하여 SQL Server 데이터베이스에 대한 상태 검사를 실행합니다. AspNetCore.Diagnostics.HealthChecks는 데이터베이스에 연결이 양호한지 확인하기 위해 데이터베이스에 대해 SELECT 1 쿼리를 실행합니다.

Warning

쿼리로 데이터베이스 연결을 검사할 때 신속하게 반환되는 쿼리를 선택합니다. 쿼리 방식 실행은 데이터베이스의 오버로드와 성능 저하를 유발할 수 있습니다. 대부분의 경우 테스트 쿼리를 실행할 필요가 없습니다. 간단히 데이터베이스에 연결하는 정도로도 충분합니다. 쿼리를 실행해야 하는 경우 SELECT 1과 같은 간단한 SELECT 쿼리를 선택합니다.

AspNetCore.HealthChecks.SqlServer에 대한 패키지 참조를 포함합니다.

샘플 앱의 appsettings.json 파일에서 유효한 데이터베이스 연결 문자열을 제공합니다. 앱은 HealthCheckSample이라고 하는 SQL Server 데이터베이스를 사용합니다.

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\MSSQLLocalDB;Database=HealthCheckSample;Trusted_Connection=True;MultipleActiveResultSets=true;ConnectRetryCount=0"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Console": {
      "IncludeScopes": "true"
    }
  },
  "AllowedHosts": "*"
}

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. 샘플 앱은 데이터베이스의 연결 문자열(DbHealthStartup.cs)를 사용하여 메서드를 호출 AddSqlServer 합니다.

services.AddHealthChecks()
    .AddSqlServer(Configuration["ConnectionStrings:DefaultConnection"]);

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

샘플 앱을 사용하여 데이터베이스 프로브 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario db

참고 항목

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

Entity Framework Core DbContext 프로브

DbContext 검사는 앱이 EF CoreDbContext에 대해 구성된 데이터베이스와 통신할 수 있음을 확인합니다. DbContext 검사는 다음과 같은 앱에서 지원됩니다.

AddDbContextCheck<TContext>DbContext에 대한 상태 검사를 등록합니다. DbContext는 메서드에 TContext로 제공됩니다. 오버로드는 오류 상태, 태그 및 사용자 지정 테스트 쿼리를 구성할 수 있습니다.

기본적으로:

  • DbContextHealthCheck는 EF Core의 CanConnectAsync 메서드를 호출합니다. AddDbContextCheck 메서드 오버로드를 사용하여 상태를 검사할 때 실행되는 작업을 사용자 정의할 수 있습니다.
  • 상태 검사의 이름은 TContext 형식의 이름입니다.

샘플 앱에서 AppDbContextAddDbContextCheck에 제공되고 Startup.ConfigureServices의 서비스로 등록됩니다(DbContextHealthStartup.cs).

services.AddHealthChecks()
    .AddDbContextCheck<AppDbContext>();

services.AddDbContext<AppDbContext>(options =>
{
    options.UseSqlServer(
        Configuration["ConnectionStrings:DefaultConnection"]);
});

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health");
}

샘플 앱을 사용하여 DbContext 프로브 시나리오를 실행하려면 연결 문자열로 지정된 데이터베이스가 SQL Server 인스턴스에 있지 않은지 확인합니다. 데이터베이스가 있으면 삭제합니다.

명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario dbcontext

앱을 실행한 후 브라우저의 /health 엔드포인트에 요청하여 상태를 검사합니다. 데이터베이스 및 AppDbContext가 존재하기 않기 때문에 앱은 다음 응답을 제공합니다.

Unhealthy

데이터베이스를 만드는 샘플 앱을 트리거합니다. /createdatabase에 요청합니다. 앱은 다음과 같이 응답합니다.

Creating the database...
Done!
Navigate to /health to see the health status.

/health 엔드포인트에 요청합니다. 데이터베이스와 컨텍스트가 존재하기 때문에 앱은 다음과 같이 응답합니다.

Healthy

데이터베이스를 삭제하는 샘플 앱을 트리거합니다. /deletedatabase에 요청합니다. 앱은 다음과 같이 응답합니다.

Deleting the database...
Done!
Navigate to /health to see the health status.

/health 엔드포인트에 요청합니다. 앱은 다음과 같이 비정상 응답을 제공합니다.

Unhealthy

별도의 준비 상태 및 활동성 프로브

일부 호스팅 시나리오에서 두 가지 앱 상태를 구분하는 한 쌍의 상태 검사가 사용됩니다.

  • ‘준비 상태’는 앱이 정상적으로 실행 중이지만 요청을 받을 준비가 되지 않았음을 나타냅니다.
  • ‘활동성’은 앱의 작동이 중단되어 다시 시작해야 함을 나타냅니다.

다음 예제를 고려하세요. 앱은 요청을 처리할 준비가 되기 전에 큰 구성 파일을 다운로드해야 합니다. 앱에서 파일 다운로드를 여러 번 다시 시도할 수 있으므로 초기 다운로드가 실패하더라도 앱을 다시 시작하지 않는 것이 좋습니다. 활동성 프로브를 사용하여 프로세스의 활동성을 설명하며 다른 검사를 실행하지 않습니다. 또한 구성 파일이 다운로드되기 전에는 앱에 요청을 보내지 못하게 합니다. ‘준비 상태 프로브’를 사용하여 다운로드에 성공하여 앱이 요청을 받을 준비가 될 때까지 “준비되지 않음” 상태를 표시합니다.

샘플 앱에는 호스팅된 서비스에서 장기 실행 시작 작업 완료를 보고하는 상태 검사가 있습니다. 호스트 StartupHostedServiceHealthCheck 된 서비스가 장기 실행 작업이 완료된 시점으로 true 설정할 수 있는 속성을 StartupTaskCompleted노출합니다()StartupHostedServiceHealthCheck.cs.

public class StartupHostedServiceHealthCheck : IHealthCheck
{
    private volatile bool _startupTaskCompleted = false;

    public string Name => "slow_dependency_check";

    public bool StartupTaskCompleted
    {
        get => _startupTaskCompleted;
        set => _startupTaskCompleted = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        if (StartupTaskCompleted)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("The startup task is finished."));
        }

        return Task.FromResult(
            HealthCheckResult.Unhealthy("The startup task is still running."));
    }
}

장기 실행 백그라운드 작업은 호스팅된 서비스(Services/StartupHostedService)에 의해 시작됩니다. 작업이 끝나면 StartupHostedServiceHealthCheck.StartupTaskCompletedtrue로 설정됩니다.

public class StartupHostedService : IHostedService, IDisposable
{
    private readonly int _delaySeconds = 15;
    private readonly ILogger _logger;
    private readonly StartupHostedServiceHealthCheck _startupHostedServiceHealthCheck;

    public StartupHostedService(ILogger<StartupHostedService> logger,
        StartupHostedServiceHealthCheck startupHostedServiceHealthCheck)
    {
        _logger = logger;
        _startupHostedServiceHealthCheck = startupHostedServiceHealthCheck;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is starting.");

        // Simulate the effect of a long-running startup task.
        Task.Run(async () =>
        {
            await Task.Delay(_delaySeconds * 1000);

            _startupHostedServiceHealthCheck.StartupTaskCompleted = true;

            _logger.LogInformation("Startup Background Service has started.");
        });

        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Startup Background Service is stopping.");

        return Task.CompletedTask;
    }

    public void Dispose()
    {
    }
}

상태 검사는 호스팅된 서비스와 함께 Startup.ConfigureServicesAddCheck에 등록됩니다. 호스트된 서비스는 상태 검사 속성을 설정해야 하므로 상태 검사 서비스 컨테이너(LivenessProbeStartup.cs)에도 등록됩니다.

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다. 샘플 앱에서 상태 검사 엔드포인트는 다음 위치에 만들어집니다.

  • 준비 상태 검사를 위해 /health/ready. 준비 상태 검사는 ready 태그가 있는 상태 검사에서 상태 검사를 필터링합니다.
  • 활동성 검사를 위해 /health/live. 활동성 검사는 HealthCheckOptions.Predicate에서 false를 반환하여 StartupHostedServiceHealthCheck를 필터링합니다(자세한 내용은 상태 검사 필터링에서 참조).

다음 예제 코드에서:

  • 준비 상태 검사는 'ready' 태그가 있는 등록된 검사를 모두 사용합니다.
  • Predicate는 모든 검사를 제외하고 200-Ok를 반환합니다.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

샘플 앱을 사용하여 준비 상태/활동성 구성 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario liveness

브라우저에서 15초가 경과할 때까지 /health/ready를 여러 번 방문합니다. 상태 검사는 첫 15초 동안 Unhealthy를 보고합니다. 15초 후, 엔드포인트는 Healthy를 보고하여 호스팅된 서비스에 의해 장기 실행 작업이 완료되었음을 나타냅니다.

이 예제에서는 2초 지연을 사용하여 첫 번째 준비 검사를 실행하는 상태 검사 게시자(IHealthCheckPublisher 구현)도 만듭니다. 자세한 내용은 상태 검사 게시자 섹션을 참조하세요.

Kubernetes 예제

별도의 준비 상태 및 활동성 검사를 사용하는 것은 Kubernetes와 같은 환경에서 유용합니다. Kubernetes에서 앱은 기본 데이터베이스 가용성 테스트와 같이 요청을 수락하기 전에 시간이 많이 걸리는 시작 작업을 실행해야 할 수도 있습니다. 별도의 검사를 사용하면 오케스트레이터가 앱이 작동하고 있지만 아직 준비가 되지 않았는지 또는 앱이 시작되지 않았는지 구분할 수 있습니다. Kubernetes의 준비 상태 및 활동성 프로브에 대한 자세한 내용은 Kubernetes 설명서의 활동성 및 준비 상태 프로브 구성을 참조하세요.

다음 예제는 Kubernetes 준비 상태 프로브 구성을 보여줍니다.

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /health/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

사용자 지정 응답 기록기가 있는 메트릭 기반 프로브

샘플 앱은 사용자 지정 응답 기록기가 있는 메모리 상태를 보여줍니다.

앱이 일정한 메모리 임계값(샘플 앱의 경우 1GB)을 초과하여 사용하는 경우 MemoryHealthCheck는 성능이 저하된 상태를 보고합니다. HealthCheckResult에는 앱의 가비지 수집기(GC) 정보가 포함됩니다(MemoryHealthCheck.cs).

public class MemoryHealthCheck : IHealthCheck
{
    private readonly IOptionsMonitor<MemoryCheckOptions> _options;

    public MemoryHealthCheck(IOptionsMonitor<MemoryCheckOptions> options)
    {
        _options = options;
    }

    public string Name => "memory_check";

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        var options = _options.Get(context.Registration.Name);

        // Include GC information in the reported diagnostics.
        var allocated = GC.GetTotalMemory(forceFullCollection: false);
        var data = new Dictionary<string, object>()
        {
            { "AllocatedBytes", allocated },
            { "Gen0Collections", GC.CollectionCount(0) },
            { "Gen1Collections", GC.CollectionCount(1) },
            { "Gen2Collections", GC.CollectionCount(2) },
        };
        var status = (allocated < options.Threshold) ?
            HealthStatus.Healthy : context.Registration.FailureStatus;

        return Task.FromResult(new HealthCheckResult(
            status,
            description: "Reports degraded status if allocated bytes " +
                $">= {options.Threshold} bytes.",
            exception: null,
            data: data));
    }
}

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. AddCheck에 전달하여 상태 검사를 사용하는 대신 MemoryHealthCheck는 서비스로 등록됩니다. 모든 IHealthCheck 등록된 서비스는 상태 검사 서비스 및 미들웨어에 사용할 수 있습니다. 상태 확인 서비스를 Singleton 서비스로 등록하는 것이 좋습니다.

CustomWriterStartup.cs 샘플 앱에서 다음을 수행합니다.

services.AddHealthChecks()
    .AddMemoryHealthCheck("memory");

상태 검사 엔드포인트는 Startup.Configure에서 MapHealthChecks를 호출하여 만듭니다. 상태 검사가 실행될 때 사용자 정의 JSON 응답을 출력하기 위해 ResponseWriter 속성에 WriteResponse 대리자가 제공됩니다.

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health", new HealthCheckOptions()
    {
        ResponseWriter = WriteResponse
    });
}

WriteResponse 대리자는 CompositeHealthCheckResult를 JSON 객체로 형식 지정하고 상태 검사 응답을 위해 JSON 출력을 생성합니다. 자세한 내용은 출력 사용자 지정 섹션을 참조하세요.

샘플 앱을 사용하여 사용자 지정 응답 기록기 출력으로 메트릭 기반 프로브를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario writer

참고 항목

AspNetCore.Diagnostics.HealthChecks에는 디스크 스토리지 및 최댓값 활동성 검사를 포함하여 메트릭 기반 상태 확인 시나리오가 포함됩니다.

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

포트별 필터링

지정된 포트에 대한 상태 검사 요청을 제한하는 포트를 지정하는 URL 패턴을 사용하여 MapHealthChecksRequireHost를 호출합니다. 이 방법은 일반적으로 컨테이너 환경에서 서비스 모니터링을 위해 포트를 노출하는 데 사용됩니다.

샘플 앱은 환경 변수 구성 공급자를 사용하여 포트를 구성합니다. 포트는 launchSettings.json 파일에서 설정되고 환경 변수를 통해 구성 공급자에게 전달됩니다. 또한 관리 포트에서 요청을 수신하도록 서버를 구성해야 합니다.

샘플 앱을 사용하여 관리 포트 구성을 보여 주려면 폴더에 launchSettings.jsonProperties 파일을 만듭니다.

다음 Properties/launchSettings.json 파일은 샘플 앱의 프로젝트 파일에 포함되지 않으며 수동으로 만들어야 합니다.

{
  "profiles": {
    "SampleApp": {
      "commandName": "Project",
      "commandLineArgs": "",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development",
        "ASPNETCORE_URLS": "http://localhost:5000/;http://localhost:5001/",
        "ASPNETCORE_MANAGEMENTPORT": "5001"
      },
      "applicationUrl": "http://localhost:5000/"
    }
  }
}

Startup.ConfigureServicesAddHealthChecks에 상태 검사 서비스를 등록합니다. Startup.Configure에서 MapHealthChecks를 호출하여 상태 검사 엔드포인트를 만듭니다.

샘플 앱에서 Startup.Configure의 엔드포인트에 대한 RequireHost 호출은 구성의 관리 포트를 지정합니다.

endpoints.MapHealthChecks("/health")
    .RequireHost($"*:{Configuration["ManagementPort"]}");

샘플 앱에서 엔드포인트는 Startup.Configure에서 만들어집니다. 다음 예제 코드에서:

  • 준비 상태 검사는 'ready' 태그가 있는 등록된 검사를 모두 사용합니다.
  • Predicate는 모든 검사를 제외하고 200-Ok를 반환합니다.
app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health/ready", new HealthCheckOptions()
    {
        Predicate = (check) => check.Tags.Contains("ready"),
    });

    endpoints.MapHealthChecks("/health/live", new HealthCheckOptions()
    {
        Predicate = (_) => false
    });
}

참고 항목

코드에서 관리 포트를 명시적으로 설정하여 샘플 앱에 launchSettings.json 파일을 만들지 않도록 할 수 있습니다. Program.cs 생성되는 위치에서 HostBuilder 호출을 ListenAnyIP 추가하고 앱의 관리 포트 엔드포인트를 제공합니다. ManagementPortStartup.csConfigure에서 RequireHost로 관리 포트를 지정합니다.

Program.cs:

return new HostBuilder()
    .ConfigureWebHostDefaults(webBuilder =>
    {
        webBuilder.UseKestrel()
            .ConfigureKestrel(serverOptions =>
            {
                serverOptions.ListenAnyIP(5001);
            })
            .UseStartup(startupType);
    })
    .Build();

ManagementPortStartup.cs:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHealthChecks("/health").RequireHost("*:5001");
});

샘플 앱을 사용하여 관리 포트 구성 시나리오를 실행하려면 명령 셸의 프로젝트 폴더에서 다음 명령을 실행합니다.

dotnet run --scenario port

상태 검사 라이브러리 배포

상태 검사를 라이브러리로 배포하려면 다음과 같이 수행합니다.

  1. IHealthCheck 인터페이스를 독립 실행형 클래스로 구현하는 상태 검사를 기록합니다. 클래스는 DI(종속성 주입), 유형 활성화 및 명명된 옵션에 의존하여 구성 데이터에 액세스할 수 있습니다.

    CheckHealthAsync의 상태 검사 논리에서:

    • data1data2는 메서드에서 프로브의 상태 검사 논리를 실행하는 데 사용됩니다.
    • AccessViolationException이 처리됩니다.

    AccessViolationException이 발생하는 경우 사용자가 상태 검사 실패 상태를 구성할 수 있도록 FailureStatusHealthCheckResult와 함께 반환됩니다.

    using System;
    using System.Threading;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    namespace SampleApp
    {
        public class ExampleHealthCheck : IHealthCheck
        {
            private readonly string _data1;
            private readonly int? _data2;
    
            public ExampleHealthCheck(string data1, int? data2)
            {
                _data1 = data1 ?? throw new ArgumentNullException(nameof(data1));
                _data2 = data2 ?? throw new ArgumentNullException(nameof(data2));
            }
    
            public async Task<HealthCheckResult> CheckHealthAsync(
                HealthCheckContext context, CancellationToken cancellationToken)
            {
                try
                {
                    return HealthCheckResult.Healthy();
                }
                catch (AccessViolationException ex)
                {
                    return new HealthCheckResult(
                        context.Registration.FailureStatus,
                        description: "An access violation occurred during the check.",
                        exception: ex,
                        data: null);
                }
            }
        }
    }
    
  2. 사용하는 앱이 Startup.Configure 메서드에서 호출하는 매개 변수를 사용하여 확장 메서드를 기록합니다. 다음 예제에서는 다음 상태 검사 메서드 서명을 가정합니다.

    ExampleHealthCheck(string, string, int )
    

    이전 서명은 ExampleHealthCheck가 상태 검사 프로브 로직을 처리하기 위해 추가 데이터가 필요함을 나타냅니다. 상태 검사가 확장 메서드를 사용하여 등록되면 데이터는 상태 검사 인스턴스를 만드는 데 사용된 대리자에게 제공됩니다. 다음 예제에서 호출자는 선택 사항을 지정합니다.

    • 상태 검사 이름(name). null인 경우 example_health_check가 사용됩니다.
    • 상태 검사를 위한 문자열 데이터 요소입니다(data1).
    • 상태 검사를 위한 정수 데이터 요소입니다(data2). null인 경우 1가 사용됩니다.
    • 실패 상태입니다(HealthStatus). 기본값은 null입니다. null인 경우 HealthStatus.Unhealthy는 오류 상태에 대해 보고됩니다.
    • 태그(IEnumerable<string>)입니다.
    using System.Collections.Generic;
    using Microsoft.Extensions.Diagnostics.HealthChecks;
    
    public static class ExampleHealthCheckBuilderExtensions
    {
        const string DefaultName = "example_health_check";
    
        public static IHealthChecksBuilder AddExampleHealthCheck(
            this IHealthChecksBuilder builder,
            string name = default,
            string data1,
            int data2 = 1,
            HealthStatus? failureStatus = default,
            IEnumerable<string> tags = default)
        {
            return builder.Add(new HealthCheckRegistration(
                name ?? DefaultName,
                sp => new ExampleHealthCheck(data1, data2),
                failureStatus,
                tags));
        }
    }
    

상태 검사 게시자

IHealthCheckPublisher가 서비스 컨테이너에 추가되면 상태 검사 시스템이 주기적으로 상태 검사를 실행하고 그 결과로 PublishAsync를 호출합니다. 이는 각 프로세스가 상태를 결정하기 위해 주기적으로 모니터링 시스템을 호출하도록 하는 푸시 기반 상태 모니터링 시스템 시나리오에서 유용합니다.

IHealthCheckPublisher 인터페이스는 단일 메서드를 가집니다.

Task PublishAsync(HealthReport report, CancellationToken cancellationToken);

HealthCheckPublisherOptions를 사용하여 다음을 설정할 수 있습니다.

  • Delay: 인스턴스를 실행 IHealthCheckPublisher 하기 전에 앱이 시작된 후 적용되는 초기 지연입니다. 지연은 시작 시 한 번 적용되며 후속 반복에는 적용되지 않습니다. 기본값은 5초입니다.
  • Period: 실행 기간입니다 IHealthCheckPublisher . 기본값은 30초입니다.
  • Predicate: 기본값인 null 경우 Predicate 상태 검사 게시자 서비스는 등록된 모든 상태 검사 실행합니다. 상태 검사 하위 집합을 실행하려면 검사 세트를 필터링하는 함수를 제공합니다. 조건자는 기간마다 평가됩니다.
  • Timeout: 모든 IHealthCheckPublisher 인스턴스에 대한 상태 검사 실행하기 위한 시간 제한입니다. 시간 제한 없이 실행하려면 InfiniteTimeSpan을 사용합니다. 기본값은 30초입니다.

샘플 앱에서 ReadinessPublisherIHealthCheckPublisher 구현입니다. 상태 검사 상태는 다음의 로그 수준에서 각 검사에 대해 기록됩니다.

public class ReadinessPublisher : IHealthCheckPublisher
{
    private readonly ILogger _logger;

    public ReadinessPublisher(ILogger<ReadinessPublisher> logger)
    {
        _logger = logger;
    }

    // The following example is for demonstration purposes only. Health Checks
    // Middleware already logs health checks results. A real-world readiness
    // check in a production app might perform a set of more expensive or
    // time-consuming checks to determine if other resources are responding
    // properly.
    public Task PublishAsync(HealthReport report,
        CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            _logger.LogInformation("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }
        else
        {
            _logger.LogError("{Timestamp} Readiness Probe Status: {Result}",
                DateTime.UtcNow, report.Status);
        }

        cancellationToken.ThrowIfCancellationRequested();

        return Task.CompletedTask;
    }
}

샘플 앱의 LivenessProbeStartup 예제에서 StartupHostedService 준비 검사에는 2초 시작 지연이 있고 30초마다 검사가 실행됩니다. IHealthCheckPublisher 구현을 활성화하기 위해 샘플은 DI(종속성 주입) 컨테이너에서 ReadinessPublisher를 싱글톤 서비스로 등록합니다.

services.AddHostedService<StartupHostedService>();
services.AddSingleton<StartupHostedServiceHealthCheck>();

services.AddHealthChecks()
    .AddCheck<StartupHostedServiceHealthCheck>(
        "hosted_service_startup",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "ready" });

services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = (check) => check.Tags.Contains("ready");
});

services.AddSingleton<IHealthCheckPublisher, ReadinessPublisher>();

참고 항목

AspNetCore.Diagnostics.HealthChecks에는 Application Insights를 포함하여 몇몇 시스템에 대한 게시자를 포함합니다.

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

MapWhen으로 상태 검사 제한

MapWhen을 사용하여 상태 검사 엔드포인트에 대한 요청 파이프라인을 조건부로 분기합니다.

다음 예제에서 MapWhenapi/HealthCheck 엔드포인트에 대한 GET 요청을 받는 경우 상태 검사 미들웨어를 활성화하도록 요청 파이프라인을 분기합니다.

app.MapWhen(
    context => context.Request.Method == HttpMethod.Get.Method && 
        context.Request.Path.StartsWith("/api/HealthCheck"),
    builder => builder.UseHealthChecks());

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});

자세한 내용은 ASP.NET Core 미들웨어를 참조하세요.

ASP.NET Core는 앱 인프라 구성 요소의 상태를 보고하기 위해 상태 검사 미들웨어와 라이브러리를 제공합니다.

상태 검사는 앱에 의해 HTTP 엔드포인트로서 노출됩니다. 상태 검사 엔드포인트는 다양한 실시간 모니터링 시나리오에 맞게 구성할 수 있습니다.

  • 상태 프로브는 컨테이너 오케스트레이터와 부하 분산 장치가 앱 상태를 검사하는 데 사용할 수 있습니다. 예를 들어, 컨테이너 오케스트레이터는 롤링 배포를 중지하거나 컨테이너를 다시 시작하여 실패한 상태 검사에 응답할 수 있습니다. 부하 분산 장치는 장애가 발생한 상태 검사 인스턴스로부터 트래픽을 다른 곳으로 라우팅하여 비정상 앱에 대응할 수 있습니다.
  • 메모리, 디스크 및 기타 물리적 서버 리소스의 사용이 정상적인 상태인지 모니터링할 수 있습니다.
  • 상태 검사는 데이터베이스 및 외부 서비스 엔드포인트와 같은 앱 종속성을 테스트하여 가용성 및 정상 작동 여부를 확인할 수 있습니다.

상태 검사는 일반적으로 외부 모니터링 서비스 또는 컨테이너 오케스트레이터와 함께 사용되어 앱 상태를 검사합니다. 앱에 상태 검사를 추가하기 전에 사용할 모니터링 시스템을 결정합니다. 모니터링 시스템은 어떤 유형의 상태 검사를 만들고 그 엔드포인트를 구성하는 방법을 지정합니다.

기본 상태 프로브

많은 앱의 경우, 요청을 처리할 수 있는 앱의 가용성(활동성)을 보고하는 기본 상태 검사 구성으로 앱 상태를 충분히 파악할 수 있습니다.

기본 구성은 상태 검사 서비스를 등록하고 상태 검사 미들웨어를 호출하여 URL 엔드포인트에서 상태 응답을 사용하여 응답합니다. 기본적으로 특정 종속성이나 하위 시스템을 테스트하기 위해 특정 상태 검사가 등록되지 않습니다. 앱은 상태 엔드포인트 URL에서 응답할 수 있는 경우 정상으로 간주됩니다. 기본 응답 기록기는 HealthStatus를 클라이언트에 일반 텍스트 응답으로 씁니다. HealthStatusHealthStatus.Healthy, HealthStatus.Degraded 또는 HealthStatus.Unhealthy입니다.

Program.csAddHealthChecks에 상태 검사 서비스를 등록합니다. MapHealthChecks를 호출하여 상태 검사 엔드포인트를 만듭니다.

다음 예제에서는 /healthz에서 상태 검사 엔드포인트를 만듭니다.

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks();

var app = builder.Build();

app.MapHealthChecks("/healthz");

app.Run();

Docker HEALTHCHECK

Docker는 기본 상태 검사 구성을 사용하는 앱의 상태를 검사하는 데 사용할 수 있는 기본 제공 HEALTHCHECK 지시문을 제공합니다.

HEALTHCHECK CMD curl --fail http://localhost:5000/healthz || exit

앞의 예제에서는 curl을 사용하여 /healthz에서 상태 검사 엔드포인트에 대한 HTTP 요청을 수행합니다. curl은 .NET Linux 컨테이너 이미지에 포함되지 않지만 Dockerfile에서 필요한 패키지를 설치하여 추가할 수 있습니다. Alpine Linux를 기반으로 하는 이미지를 사용하는 컨테이너는 curl 대신 포함된 wget을 사용할 수 있습니다.

상태 검사 만들기

상태 검사는 IHealthCheck 인터페이스를 구현하여 만듭니다. CheckHealthAsync 메서드는 상태를 Healthy, Degraded 또는 Unhealthy로 나타내는 HealthCheckResult를 반환합니다. 결과는 구성 가능한 상태 코드가 포함된 일반 텍스트 응답으로 작성됩니다. 구성은 상태 검사 옵션 섹션에 설명되어 있습니다. HealthCheckResult는 선택 사항인 키-값 쌍을 반환할 수도 있습니다.

다음 예제에서는 상태 검사의 레이아웃을 보여줍니다.

public class SampleHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

상태 검사의 논리는 CheckHealthAsync 메서드에 배치됩니다. 앞의 예제에서는 더미 변수 isHealthytrue로 설정합니다. isHealthy 값이 false로 설정되면 HealthCheckRegistration.FailureStatus 상태가 반환됩니다.

CheckHealthAsync가 검사 중에 예외를 throw하면 해당 HealthReportEntry.StatusFailureStatus로 설정된 상태로 새 HealthReportEntry가 반환됩니다. 이 상태는 AddCheck에 의해 정의되며(상태 검사 서비스 등록 섹션 참조) 검사 실패를 초래한 내부 예외가 포함되어 있습니다. Description은 예외의 메시지로 설정됩니다.

상태 검사 서비스 등록

상태 검사 서비스를 등록하려면 Program.cs에서 AddCheck를 호출합니다.

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>("Sample");

다음 예제에 표시된 AddCheck 오버로드는 상태 검사에서 오류가 보고되면 보고하도록 오류 상태(HealthStatus)를 설정합니다. 오류 상태가 null(기본값)로 설정되면 HealthStatus.Unhealthy가 보고됩니다. 이 오버로드는 라이브러리 작성자에게 유용한 시나리오입니다. 이 라이브러리에서는 상태 검사 구현이 설정을 준수하는 경우 상태 검사 실패가 발생할 때 라이브러리가 나타내는 오류 상태는 앱에 의해 적용됩니다.

상태 검사를 필터링하기 위해 태그를 사용할 수 있습니다. 태그는 상태 검사 필터링 섹션에 설명되어 있습니다.

builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheck>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" });

AddCheck는 람다 함수를 실행할 수도 있습니다. 다음 예제에서 상태 검사는 항상 정상 결과를 반환합니다.

builder.Services.AddHealthChecks()
    .AddCheck("Sample", () => HealthCheckResult.Healthy("A healthy result."));

AddTypeActivatedCheck를 호출하여 상태 검사 구현에 인수를 전달합니다. 다음 예제에서 형식 활성화 상태 검사는 해당 생성자의 정수 및 문자열을 허용합니다.

public class SampleHealthCheckWithArgs : IHealthCheck
{
    private readonly int _arg1;
    private readonly string _arg2;

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        // ...

        return Task.FromResult(HealthCheckResult.Healthy("A healthy result."));
    }
}

위의 상태 검사를 등록하려면 인수로 전달된 정수 및 문자열을 사용하여 AddTypeActivatedCheck를 호출합니다.

builder.Services.AddHealthChecks()
    .AddTypeActivatedCheck<SampleHealthCheckWithArgs>(
        "Sample",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "sample" },
        args: new object[] { 1, "Arg" });

상태 검사 라우팅 사용

Program.cs에서 엔드포인트 URL 또는 상대 경로를 사용하여 엔드포인트 작성기에 MapHealthChecks를 호출합니다.

app.MapHealthChecks("/healthz");

호스트 필요

RequireHost를 호출하여 상태 검사 엔드포인트에 대해 허용된 호스트를 하나 이상 지정합니다. 호스트는 punycode가 아닌 유니코드여야 하고 포트를 포함할 수 있습니다. 컬렉션을 제공하지 않으면 모든 호스트가 허용됩니다.

app.MapHealthChecks("/healthz")
    .RequireHost("www.contoso.com:5001");

상태 검사 엔드포인트가 특정 포트에서만 응답하도록 제한하려면 RequireHost에 대한 호출에서 포트를 지정합니다. 이 방법은 일반적으로 컨테이너 환경에서 서비스 모니터링을 위해 포트를 노출하는 데 사용됩니다.

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001");

Warning

호스트 헤더(예: HttpRequest.HostRequireHost)를 사용하는 API는 클라이언트에서 스푸핑될 수 있습니다.

호스트 및 포트 스푸핑을 방지하려면 다음 방법 중 하나를 사용합니다.

권한이 없는 클라이언트가 포트를 스푸핑하지 못하도록 하려면 다음을 호출 RequireAuthorization합니다.

app.MapHealthChecks("/healthz")
    .RequireHost("*:5001")
    .RequireAuthorization();

자세한 내용은 RequireHost가 있는 경로에서 호스트 일치를 참조하세요.

권한 부여 필요

RequireAuthorization을 호출하여 상태 검사 요청 엔드포인트에서 권한 부여 미들웨어를 실행합니다. RequireAuthorization 오버로드는 하나 이상의 권한 부여 정책을 허용합니다. 정책을 제공하지 않으면 기본 권한 부여 정책이 사용됩니다.

app.MapHealthChecks("/healthz")
    .RequireAuthorization();

원본 간 요청(CORS) 사용

브라우저에서 수동으로 상태 검사를 실행하는 것이 일반적이지는 않지만, 상태 검사 엔드포인트에 RequireCors를 호출하여 CORS 미들웨어를 사용하도록 설정할 수 있습니다. RequireCors 오버로드는 CORS 정책 작성기 대리자(CorsPolicyBuilder) 또는 정책 이름을 허용합니다. 자세한 내용은 ASP.NET Core에서 CORS(원본 간 요청) 사용을 참조하세요.

상태 검사 옵션

HealthCheckOptions는 다음과 같은 상태 검사 동작을 사용자 지정할 수 있는 기회를 제공합니다.

상태 검사 필터링

기본적으로 상태 검사 미들웨어는 등록된 모든 상태 검사를 실행합니다. 상태 검사 하위 세트를 실행하려면 Predicate 옵션에 부울 값을 반환하는 함수를 제공합니다.

다음 예제에서는 sample 태그가 지정된 상태 검사만 실행되도록 상태 검사를 필터링합니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("sample")
});

HTTP 상태 코드 사용자 지정

ResultStatusCodes를 사용하여 상태를 HTTP 상태 코드에 매핑하는 작업을 사용자 지정할 수 있습니다. 다음 StatusCodes 할당은 미들웨어에서 사용되는 기본값입니다. 요구 사항에 맞게 상태 코드 값을 변경합니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResultStatusCodes =
    {
        [HealthStatus.Healthy] = StatusCodes.Status200OK,
        [HealthStatus.Degraded] = StatusCodes.Status200OK,
        [HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
    }
});

캐시 헤더 표시 안 함

AllowCachingResponses는 응답 캐싱을 방지하기 위해 상태 검사 미들웨어가 HTTP 헤더를 프로브 응답에 추가할지 여부를 제어합니다. 값이 false(기본값)인 경우 미들웨어는 응답 캐싱을 방지하기 위해 Cache-Control, ExpiresPragma 헤더를 설정하거나 재정의합니다. 값이 true인 경우 미들웨어는 응답 캐시 헤더를 수정하지 않습니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    AllowCachingResponses = true
});

출력 사용자 지정

상태 검사 보고서의 출력을 사용자 지정하려면 HealthCheckOptions.ResponseWriter 속성을 응답을 작성하는 대리자로 설정합니다.

app.MapHealthChecks("/healthz", new HealthCheckOptions
{
    ResponseWriter = WriteResponse
});

기본 대리자는 HealthReport.Status의 문자열 값을 사용하여 최소 일반 텍스트 응답을 기록합니다. 다음 사용자 지정 대리자는 System.Text.Json을 사용하여 사용자 지정 JSON 응답을 출력합니다.

private static Task WriteResponse(HttpContext context, HealthReport healthReport)
{
    context.Response.ContentType = "application/json; charset=utf-8";

    var options = new JsonWriterOptions { Indented = true };

    using var memoryStream = new MemoryStream();
    using (var jsonWriter = new Utf8JsonWriter(memoryStream, options))
    {
        jsonWriter.WriteStartObject();
        jsonWriter.WriteString("status", healthReport.Status.ToString());
        jsonWriter.WriteStartObject("results");

        foreach (var healthReportEntry in healthReport.Entries)
        {
            jsonWriter.WriteStartObject(healthReportEntry.Key);
            jsonWriter.WriteString("status",
                healthReportEntry.Value.Status.ToString());
            jsonWriter.WriteString("description",
                healthReportEntry.Value.Description);
            jsonWriter.WriteStartObject("data");

            foreach (var item in healthReportEntry.Value.Data)
            {
                jsonWriter.WritePropertyName(item.Key);

                JsonSerializer.Serialize(jsonWriter, item.Value,
                    item.Value?.GetType() ?? typeof(object));
            }

            jsonWriter.WriteEndObject();
            jsonWriter.WriteEndObject();
        }

        jsonWriter.WriteEndObject();
        jsonWriter.WriteEndObject();
    }

    return context.Response.WriteAsync(
        Encoding.UTF8.GetString(memoryStream.ToArray()));
}

상태 검사 API는 사용자가 선택한 모니터링 시스템에만 적용되는 형식이므로 복합 JSON 반환 형식에 대한 기본 제공 지원을 제공하지 않습니다. 앞의 예제에서 응답을 필요에 따라 사용자 지정합니다. System.Text.Json을 사용한 JSON 직렬화에 대한 자세한 내용은 .NET에서 JSON을 직렬화 및 역직렬화하는 방법을 참조하세요.

데이터베이스 프로브

상태 검사는 데이터베이스 쿼리를 지정하여 데이터베이스가 정상적으로 응답하는지를 나타내기 위해 부울 테스트로서 실행할 수 있습니다.

ASP.NET Core 앱에 대한 상태 검사 라이브러리인 AspNetCore.Diagnostics.HealthChecks에는 SQL Server 데이터베이스에 대해 실행되는 상태 검사가 포함됩니다. AspNetCore.Diagnostics.HealthChecks는 데이터베이스에 연결이 양호한지 확인하기 위해 데이터베이스에 대해 SELECT 1 쿼리를 실행합니다.

Warning

쿼리로 데이터베이스 연결을 검사할 때 신속하게 반환되는 쿼리를 선택합니다. 쿼리 방식 실행은 데이터베이스의 오버로드와 성능 저하를 유발할 수 있습니다. 대부분의 경우 테스트 쿼리를 실행할 필요가 없습니다. 간단히 데이터베이스에 연결하는 정도로도 충분합니다. 쿼리를 실행해야 하는 경우 SELECT 1과 같은 간단한 SELECT 쿼리를 선택합니다.

이 SQL Server 상태 검사를 사용하려면 AspNetCore.HealthChecks.SqlServer NuGet 패키지에 대한 패키지 참조를 포함합니다. 다음 예제에서는 SQL Server 상태 검사를 등록합니다.

builder.Services.AddHealthChecks()
    .AddSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection"));

참고 항목

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

Entity Framework Core DbContext 프로브

DbContext 검사는 앱이 EF CoreDbContext에 대해 구성된 데이터베이스와 통신할 수 있음을 확인합니다. DbContext 검사는 다음과 같은 앱에서 지원됩니다.

AddDbContextCheckDbContext에 대한 상태 검사를 등록합니다. DbContext는 메서드에 TContext로 제공됩니다. 오버로드는 오류 상태, 태그 및 사용자 지정 테스트 쿼리를 구성할 수 있습니다.

기본적으로:

  • DbContextHealthCheck는 EF Core의 CanConnectAsync 메서드를 호출합니다. AddDbContextCheck 메서드 오버로드를 사용하여 상태를 검사할 때 실행되는 작업을 사용자 정의할 수 있습니다.
  • 상태 검사의 이름은 TContext 형식의 이름입니다.

다음 예제에서는 DbContext 및 연결된 DbContextHealthCheck를 등록합니다.

builder.Services.AddDbContext<SampleDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddHealthChecks()
    .AddDbContextCheck<SampleDbContext>();

별도의 준비 상태 및 활동성 프로브

일부 호스팅 시나리오에서 두 가지 앱 상태를 구분하는 한 쌍의 상태 검사가 사용됩니다.

  • ‘준비 상태’는 앱이 정상적으로 실행 중이지만 요청을 받을 준비가 되지 않았음을 나타냅니다.
  • ‘활동성’은 앱의 작동이 중단되어 다시 시작해야 함을 나타냅니다.

다음 예제를 고려하세요. 앱은 요청을 처리할 준비가 되기 전에 큰 구성 파일을 다운로드해야 합니다. 앱에서 파일 다운로드를 여러 번 다시 시도할 수 있으므로 초기 다운로드가 실패하더라도 앱을 다시 시작하지 않는 것이 좋습니다. 활동성 프로브를 사용하여 프로세스의 활동성을 설명하며 다른 검사를 실행하지 않습니다. 또한 구성 파일이 다운로드되기 전에는 앱에 요청을 보내지 못하게 합니다. ‘준비 상태 프로브’를 사용하여 다운로드에 성공하여 앱이 요청을 받을 준비가 될 때까지 “준비되지 않음” 상태를 표시합니다.

다음 백그라운드 작업은 약 15초가 걸리는 시작 프로세스를 시뮬레이션합니다. 완료되면 작업이 StartupHealthCheck.StartupCompleted 속성을 true로 설정합니다.

public class StartupBackgroundService : BackgroundService
{
    private readonly StartupHealthCheck _healthCheck;

    public StartupBackgroundService(StartupHealthCheck healthCheck)
        => _healthCheck = healthCheck;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // Simulate the effect of a long-running task.
        await Task.Delay(TimeSpan.FromSeconds(15), stoppingToken);

        _healthCheck.StartupCompleted = true;
    }
}

StartupHealthCheck는 장기 실행 시작 작업의 완료를 보고하고 백그라운드 서비스에 의해 설정되는 StartupCompleted 속성을 노출합니다.

public class StartupHealthCheck : IHealthCheck
{
    private volatile bool _isReady;

    public bool StartupCompleted
    {
        get => _isReady;
        set => _isReady = value;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        if (StartupCompleted)
        {
            return Task.FromResult(HealthCheckResult.Healthy("The startup task has completed."));
        }

        return Task.FromResult(HealthCheckResult.Unhealthy("That startup task is still running."));
    }
}

상태 검사는 호스팅된 서비스와 함께 Program.csAddCheck에 등록됩니다. 호스팅된 서비스가 상태 검사에서 속성을 설정해야 하므로 상태 검사도 서비스 컨테이너에 싱글톤으로 등록됩니다.

builder.Services.AddHostedService<StartupBackgroundService>();
builder.Services.AddSingleton<StartupHealthCheck>();

builder.Services.AddHealthChecks()
    .AddCheck<StartupHealthCheck>(
        "Startup",
        tags: new[] { "ready" });

두 가지 상태 검사 엔드포인트를 만들려면 MapHealthChecks를 두 번 호출합니다.

app.MapHealthChecks("/healthz/ready", new HealthCheckOptions
{
    Predicate = healthCheck => healthCheck.Tags.Contains("ready")
});

app.MapHealthChecks("/healthz/live", new HealthCheckOptions
{
    Predicate = _ => false
});

앞의 예제에서는 다음과 같은 상태 검사 엔드포인트를 만듭니다.

  • 준비 상태 검사를 위해 /healthz/ready. 준비 상태 검사는 ready 태그가 지정된 상태 검사를 필터링합니다.
  • 활동성 검사를 위해 /healthz/live. 활동성 검사는 HealthCheckOptions.Predicate 대리자에서 false를 반환하여 모든 상태 검사를 필터링합니다. 상태 검사 필터링에 대한 자세한 내용은 이 문서의 상태 검사 필터링을 참조하세요.

시작 작업이 완료되기 전에는 /healthz/ready 엔드포인트가 Unhealthy 상태를 보고합니다. 시작 작업이 완료되면 이 엔드포인트는 Healthy 상태를 보고합니다. /healthz/live 엔드포인트는 모든 검사를 제외하고 모든 호출에 대해 Healthy 상태를 보고합니다.

Kubernetes 예제

별도의 준비 상태 및 활동성 검사를 사용하는 것은 Kubernetes와 같은 환경에서 유용합니다. Kubernetes에서 앱은 기본 데이터베이스 가용성 테스트와 같이 요청을 수락하기 전에 시간이 많이 걸리는 시작 작업을 실행해야 할 수도 있습니다. 별도의 검사를 사용하면 오케스트레이터가 앱이 작동하고 있지만 아직 준비가 되지 않았는지 또는 앱이 시작되지 않았는지 구분할 수 있습니다. Kubernetes의 준비 상태 및 활동성 프로브에 대한 자세한 내용은 Kubernetes 설명서의 활동성 및 준비 상태 프로브 구성을 참조하세요.

다음 예제는 Kubernetes 준비 상태 프로브 구성을 보여줍니다.

spec:
  template:
  spec:
    readinessProbe:
      # an http probe
      httpGet:
        path: /healthz/ready
        port: 80
      # length of time to wait for a pod to initialize
      # after pod startup, before applying health checking
      initialDelaySeconds: 30
      timeoutSeconds: 1
    ports:
      - containerPort: 80

상태 검사 라이브러리 배포

상태 검사를 라이브러리로 배포하려면 다음과 같이 수행합니다.

  1. IHealthCheck 인터페이스를 독립 실행형 클래스로 구현하는 상태 검사를 기록합니다. 클래스는 DI(종속성 주입), 유형 활성화 및 명명된 옵션에 의존하여 구성 데이터에 액세스할 수 있습니다.

  2. 사용하는 앱이 Program.cs 메서드에서 호출하는 매개 변수를 사용하여 확장 메서드를 기록합니다. 생성자 매개 변수로 arg1arg2를 허용하는 다음 예제 상태 검사를 참조하세요.

    public SampleHealthCheckWithArgs(int arg1, string arg2)
        => (_arg1, _arg2) = (arg1, arg2);
    

    위의 시그너처는 상태 검사가 상태 검사 프로브 논리를 처리하기 위해 사용자 지정 데이터가 필요함을 나타냅니다. 상태 검사가 확장 메서드를 사용하여 등록되면 데이터는 상태 검사 인스턴스를 만드는 데 사용된 대리자에게 제공됩니다. 다음 예제에서 호출자는 다음을 지정합니다.

    • arg1: 상태 검사를 위한 정수 데이터 요소입니다.
    • arg2: 상태 검사를 위한 문자열 인수입니다.
    • name: 선택적 상태 검사 이름입니다. null이면 기본값이 사용됩니다.
    • failureStatus: 실패 상태에 대해 보고되는 선택적 HealthStatus입니다. null인 경우 HealthStatus.Unhealthy가 사용됩니다.
    • tags: 태그의 선택적 IEnumerable<string> 컬렉션입니다.
    public static class SampleHealthCheckBuilderExtensions
    {
        private const string DefaultName = "Sample";
    
        public static IHealthChecksBuilder AddSampleHealthCheck(
            this IHealthChecksBuilder healthChecksBuilder,
            int arg1,
            string arg2,
            string? name = null,
            HealthStatus? failureStatus = null,
            IEnumerable<string>? tags = default)
        {
            return healthChecksBuilder.Add(
                new HealthCheckRegistration(
                    name ?? DefaultName,
                    _ => new SampleHealthCheckWithArgs(arg1, arg2),
                    failureStatus,
                    tags));
        }
    }
    

상태 검사 게시자

IHealthCheckPublisher가 서비스 컨테이너에 추가되면 상태 검사 시스템이 주기적으로 상태 검사를 실행하고 그 결과로 PublishAsync를 호출합니다. 이 프로세스는 각 프로세스가 상태를 결정하기 위해 주기적으로 모니터링 시스템을 호출하도록 하는 푸시 기반 상태 모니터링 시스템 시나리오에서 유용합니다.

HealthCheckPublisherOptions를 사용하여 다음을 설정할 수 있습니다.

  • Delay: 인스턴스를 실행 IHealthCheckPublisher 하기 전에 앱이 시작된 후 적용되는 초기 지연입니다. 지연은 시작 시 한 번 적용되며 이후의 반복에는 적용되지 않습니다. 기본값은 5초입니다.
  • Period: 실행 기간입니다 IHealthCheckPublisher . 기본값은 30초입니다.
  • Predicate: 기본값인 null 경우 Predicate 상태 검사 게시자 서비스는 등록된 모든 상태 검사 실행합니다. 상태 검사 하위 집합을 실행하려면 검사 세트를 필터링하는 함수를 제공합니다. 조건자는 기간마다 평가됩니다.
  • Timeout: 모든 IHealthCheckPublisher 인스턴스에 대한 상태 검사 실행하기 위한 시간 제한입니다. 시간 제한 없이 실행하려면 InfiniteTimeSpan을 사용합니다. 기본값은 30초입니다.

다음 예제에서는 상태 게시자의 레이아웃을 보여 줍니다.

public class SampleHealthCheckPublisher : IHealthCheckPublisher
{
    public Task PublishAsync(HealthReport report, CancellationToken cancellationToken)
    {
        if (report.Status == HealthStatus.Healthy)
        {
            // ...
        }
        else
        {
            // ...
        }

        return Task.CompletedTask;
    }
}

HealthCheckPublisherOptions 클래스는 상태 검사 게시자의 동작을 구성하기 위한 속성을 제공합니다.

다음 예제에서는 상태 검사 게시자를 싱글톤으로 등록하고 HealthCheckPublisherOptions를 구성합니다.

builder.Services.Configure<HealthCheckPublisherOptions>(options =>
{
    options.Delay = TimeSpan.FromSeconds(2);
    options.Predicate = healthCheck => healthCheck.Tags.Contains("sample");
});

builder.Services.AddSingleton<IHealthCheckPublisher, SampleHealthCheckPublisher>();

참고 항목

AspNetCore.Diagnostics.HealthChecks에는 Application Insights를 포함하여 몇몇 시스템에 대한 게시자를 포함합니다.

AspNetCore.Diagnostics.HealthChecks는 Microsoft에서 유지 관리하거나 지원하지 않습니다.

종속성 주입 및 상태 검사

종속성 주입을 사용하여 상태 검사 클래스 내에서 특정 Type 인스턴스를 사용할 수 있습니다. 종속성 주입은 상태 검사에 옵션 또는 전역 구성을 삽입하는 데 유용할 수 있습니다. 종속성 주입을 사용하는 것은 상태 검사를 구성하는 일반적인 시나리오가 아닙니다. 일반적으로 각 상태 검사는 실제 테스트와 매우 관련이 있으며 IHealthChecksBuilder 확장 메서드를 사용하여 구성됩니다.

다음 예제에서는 종속성 주입을 통해 구성 개체를 검색하는 샘플 상태 검사를 보여 줍니다.

public class SampleHealthCheckWithDI : IHealthCheck
{
    private readonly SampleHealthCheckWithDiConfig _config;

    public SampleHealthCheckWithDI(SampleHealthCheckWithDiConfig config)
        => _config = config;

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        var isHealthy = true;

        // use _config ...

        if (isHealthy)
        {
            return Task.FromResult(
                HealthCheckResult.Healthy("A healthy result."));
        }

        return Task.FromResult(
            new HealthCheckResult(
                context.Registration.FailureStatus, "An unhealthy result."));
    }
}

SampleHealthCheckWithDiConfig 및 상태 검사를 서비스 컨테이너에 추가해야 합니다.

builder.Services.AddSingleton<SampleHealthCheckWithDiConfig>(new SampleHealthCheckWithDiConfig
{
    BaseUriToCheck = new Uri("https://sample.contoso.com/api/")
});
builder.Services.AddHealthChecks()
    .AddCheck<SampleHealthCheckWithDI>(
        "With Dependency Injection",
        tags: new[] { "inject" });

UseHealthChecks 및 MapHealthChecks

호출자가 상태 검사 액세스할 수 있도록 하는 두 가지 방법이 있습니다.

  • UseHealthChecks는 미들웨어 파이프라인에서 상태 검사 요청을 처리하기 위한 미들웨어를 등록합니다.
  • MapHealthChecks는 상태 검사 엔드포인트를 등록합니다. 엔드포인트는 앱의 다른 엔드포인트와 일치하고 실행됩니다.

오버 UseHealthChecks 를 사용할 MapHealthChecks 경우의 이점은 권한 부여와 같은 엔드포인트 인식 미들웨어를 사용하고 일치 정책을 보다 세밀하게 제어할 수 있다는 점입니다. 오버 MapHealthChecks 사용 UseHealthChecks 의 주요 이점은 미들웨어 파이프라인에서 상태 검사 실행되는 위치를 정확하게 제어하는 것입니다.

UseHealthChecks:

  • 요청이 상태 검사 엔드포인트와 일치하면 파이프라인을 종료합니다. 로깅 및 기타 미들웨어와 같은 불필요한 작업을 방지하므로 단락이 바람직한 경우가 많습니다.
  • 주로 파이프라인에서 상태 검사 미들웨어를 구성하는 데 사용됩니다.
  • 포트의 경로를 비어 있거나 비어 PathString있는 null 경로와 일치시킬 수 있습니다. 지정된 포트에 대한 모든 요청에 대해 상태 검사 수행할 수 있습니다.
  • 소스 코드

MapHealthChecks 허용:

  • 상태 검사 대한 특정 경로 또는 엔드포인트 매핑
  • 상태 검사 엔드포인트에 액세스할 수 있는 URL 또는 경로의 사용자 지정
  • 여러 상태 검사 엔드포인트를 다른 경로 또는 구성으로 매핑합니다. 여러 엔드포인트 지원:
    • 다양한 유형의 상태 검사 또는 구성 요소에 대해 별도의 엔드포인트를 사용하도록 설정합니다.
    • 앱 상태의 다양한 측면을 구분하거나 상태 검사 하위 집합에 특정 구성을 적용하는 데 사용됩니다.
  • 소스 코드

추가 리소스

참고 항목

이 문서는 부분적으로 인공 지능의 도움을 받아 만들어졌습니다. 게시하기 전에 작성자가 필요에 따라 내용을 검토하고 수정했습니다. Microsoft Learn에서 AI 생성 콘텐츠를 사용할 때 지켜야 할 대한 원칙을 참조하세요.