Home > Software engineering >  Are .NET Core 6.0 Health Checks Run Sequentially or In Parallel
Are .NET Core 6.0 Health Checks Run Sequentially or In Parallel

Time:07-30

I'm currently trying to diagnose where things are taking time in my list of health checks. I have multiple health checks that call out to multiple databases. I also have a system that periodically calls the health check endpoint, but this system has an extremely short timeout period (~10 seconds).

After the monitoring system hits the 10 second timeout, it cancels the request. Currently the health checks I have only check for a cancelled request in one of the checks. This then causes the application to throw an exception which is expected.

My question is as the title says, are these health checks run sequentially one after another or are they ran in parallel. I'm trying to diagnose which DB is causing the delay and want to check if it could potentially be a check before the one that does the cancellation check.

CodePudding user response:

The Default HealthCheckService runs all checks in parallel:

foreach (var registration in registrations)
{
    tasks[index  ] = Task.Run(() => RunCheckAsync(registration, cancellationToken), cancellationToken);
}

await Task.WhenAll(tasks).ConfigureAwait(false);

That doesn't mean that health check methods are free to run expensive blocking code. Threads (and cores) that are running checks can't be used to server requests.

The Xabaril Database health check is fully asynchronous though :

    public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
    {
        try
        {
            using (var connection = new SqlConnection(_connectionString))
            {
                _beforeOpenConnectionConfigurer?.Invoke(connection);

                await connection.OpenAsync(cancellationToken);
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = _sql;
                    _ = await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
                }
                return HealthCheckResult.Healthy();
            }
        }
        catch (Exception ex)
        {
            return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
        }
    }
}
  • Related