如何在 ASP.NET/blazor 中对 POST url 进行健康检查

How to do a health check on a POST url in ASP.NET/blazor

我正在尝试在我的 Blazor 应用程序中实施健康检查。为此,我使用了 Microsoft.AspNetCore.Diagnostics.HealthChecks 包等。您可以在下面看到 sql 和 url 健康检查。

startup.cs

//using AjuaBlazorServerApp.Data;
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace AjuaBlazorServerApp
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddHostedService<PeriodicExecutor>();
            services.AddHealthChecks().AddUrlGroup(new Uri("https://api.example.com/post"),
                name: "Example Endpoint",
                failureStatus: HealthStatus.Degraded)
            .AddSqlServer(Configuration["sqlString"],
                healthQuery: "select 1",
                failureStatus: HealthStatus.Degraded,
                name: "SQL Server");
            services.AddHealthChecksUI(opt =>
            {
                opt.SetEvaluationTimeInSeconds(5); //time in seconds between check    
                opt.MaximumHistoryEntriesPerEndpoint(60); //maximum history of checks    
                opt.SetApiMaxActiveRequests(1); //api requests concurrency    
                opt.AddHealthCheckEndpoint("Ajua API", "/api/health"); //map health check api    
            }).AddInMemoryStorage();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
                endpoints.MapHealthChecks("/api/health", new HealthCheckOptions()
                {
                    Predicate = _ => true,
                    ResponseWriter = UIResponseWriter.
                    WriteHealthCheckUIResponse
                });
                endpoints.MapHealthChecksUI();
            });
        }
    }
}

sql 一个工作得很好。然而 url 健康检查 returns 出现以下错误:

Discover endpoint #0 is not responding with code in 200...299 range, the current status is MethodNotAllowed.

我想知道是否有可能设置方法类型的方法,以及是否需要将一些测试详细信息发送到端点,以便我们实际获得有效响应。

AddUrlGroup has an overload 允许您通过 httpMethod 参数指定方法。尝试使用:

.AddUrlGroup(new Uri("https://api.example.com/post"),
            httpMethod: HttpMethod.Post,
            name: "Example Endpoint",
            failureStatus: HealthStatus.Degraded)

Another overload 允许显式配置 HttpClient 和 HttpMessageHandler,添加特定默认值 headers,例如,启用压缩或重定向。

.AddUrlGroup(new Uri("https://api.example.com/post"),
            httpMethod: HttpMethod.Post,
            name: "Example Endpoint",
            configureClient: client => {
                client.DefaultRequest.Headers.IfModifiedSince=
                                DateTimeOffset.Now.AddMinutes(-10);
            },
            failureStatus: HealthStatus.Degraded)

Yet another overload allows explicitly configuring the UriHealthCheckOptions class 由其他 AddUrlGroup 重载生成:

.AddUrlGroup(uriOptions=>{
    uriOptions
        .UsePost()
        .AddUri(someUrl,setup=>{
            setup.AddCustomHeader("...","...");
    });
});

无法指定内容headers因为健康检查码doesn't send a body.

我接受了上面的答案,因为它在技术上回答了我的问题。然而,这是我最终使用的实现。基本上,您必须创建自己的自定义健康检查。

  1. 在您的项目主目录下添加一个新文件夹并相应地命名

2。在该文件夹中创建一个新的 class 并添加类似于我下面的代码

EndpointHealth.cs

using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using System.Net;
using System.IO;
using Microsoft.Extensions.Configuration;

namespace BlazorServerApp.HealthChecks
{
    public class EndpointHealth : IHealthCheck
    {
        public Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken =
         default)
        {
            
                //create a json string of parameters and send it to the endpoint
                var data = new
                {
                    test = "Example",
                };
                string jsonString = JsonSerializer.Serialize(data);
                var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://api.example.com/post");
                httpWebRequest.ContentType = Configuration["application/json"];
                httpWebRequest.Method = Configuration["POST"];
                using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                    streamWriter.Write(jsonString);
                }
                //Get the endpoint result and use it to return the appropriate health check result
                var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                if (((int)httpResponse.StatusCode) >= 200 && ((int)httpResponse.StatusCode) < 300)
                return Task.FromResult(HealthCheckResult.Healthy());
                else
                return Task.FromResult(HealthCheckResult.Unhealthy());
        }
    }
}

然后将以下代码添加到 startup.cs 文件的顶部 using BlazorServerApp.HealthChecks;

最后是下面的代码:

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddHealthChecks()
            .AddCheck<EndpointHealth>("Endpoint",null);

        }