Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2ConnectionErrorException

Ale*_*bak 6 c# kestrel-http-server

我有以下例外

Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2ConnectionErrorException:HTTP/2 连接错误(PROTOCOL_ERROR):无效的 HTTP/2 连接序言。

我将描述我的条件。我有一个非常简单的 grpc .Net Core项目,我想要制作HTTP 端点

这是 Startup.cs

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(options => options.EnableEndpointRouting = false);
        services.AddGrpc();

        services.AddHttpClient<IAnalyticApiAsker, AnalyticApiAsker>();

        // db context
        services.AddSingleton<IApplicationMongoContext, ApplicationMongoContext>();

        // repos
        services.AddTransient<IWorkspacesRepo, WorkspaceRepo>();
        services.AddTransient<IApplicationRepo, ApplicationRepo>();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            // Communication with gRPC endpoints must be made through a gRPC client.
            // To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909
            endpoints.MapGrpcService<ApplicationsService>();
            endpoints.MapGrpcService<WorkspacesService>();
        });

        // I think I have to use this middleware for get http endpoints ability ?? Right? 
        app.UseMvc();
    }
}
Run Code Online (Sandbox Code Playgroud)

和 Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}
Run Code Online (Sandbox Code Playgroud)

启动设置.json

{
  "profiles": {
    "Dashboard": {
      "commandName": "Project",
      "launchBrowser": false,
      "applicationUrl": "http://*:50053",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Local"
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

对于端点,我有以下控制器:

public class HealthController : Controller
{ 
    [Route("/healthcheck")]
    [HttpGet]
    public IActionResult Index()
    {
        return Ok(new
        {
            status = "ok",
            description = "works"
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我从浏览器请求我的应用程序的 URL 时,http://localhost:50053/healthcheck我有这个例外。看起来 Kestrel 只为 http2 配置。如果是真的,如何开启 HTTP 处理?

更新

好的,经过一些研究,我了解了以下内容。不可能同时打开两种协议类型处理:grpc(适用于 HTTP 2)和普通 http1。我对吗?

我已将我的修改Startapp.cs为:

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureKestrel(options =>
            {
                options.ListenLocalhost(50053, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
                });
            })
            .UseStartup<Startup>();
Run Code Online (Sandbox Code Playgroud)

HttpProtocols.Http1AndHttp2此属性对于每个 HTTP 类型(Http1、Http、Http1AndHttp2)都有不同的变体。但它不适用于 GRPC。我认为这是因为是否使用 http1 到 GRPC 或 http2。而且我不知道如何设置它。

所以,listenOptions.Protocols = HttpProtocols.Http1- 适用于网络, listenOptions.Protocols = HttpProtocols.Http2- 适用于 GRPC 并且 listenOptions.Protocols = HttpProtocols.Http1AndHttp2- 适用于网络。

更新 2

我不确定它是否回答,但我已经在以下Program.cs修改的帮助下解决了这个任务:

    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureKestrel(options =>
            {
                options.ListenLocalhost(80, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http1;
                });

                options.ListenLocalhost(50053, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                });
            })
            .UseStartup<Startup>();
}
Run Code Online (Sandbox Code Playgroud)

现在我可以使用 http1 和 http2。但是现在我遇到了一个新问题,它只能在本地主机上运行。

Ale*_*bak 6

好的,我已经在以下Program.cs修改的帮助下解决了它:

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .ConfigureKestrel(options =>
            {
                options.ListenAnyIP(80, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http1;
                });

                options.ListenAnyIP(50053, listenOptions =>
                {
                    listenOptions.Protocols = HttpProtocols.Http2;
                });
            })
            .UseStartup<Startup>();
}
Run Code Online (Sandbox Code Playgroud)

现在我可以同时使用 GRPC 和 http1,并且允许任何 IP 连接。

我希望它对将 http1 添加到 GRPC 配置项目的人有用。