如何在ASP.NET Core的Kestrel上为MVC与gRPC配置独立端点?
解决ASP.NET Core中MVC与gRPC绑定独立套接字的问题
嘿,这个问题我之前也踩过坑!默认情况下Kestrel会把所有端点映射应用到所有配置的套接字上,所以咱们得做些条件筛选,让MVC和gRPC分别绑定到指定端口,同时满足各自的HTTP协议要求。下面是具体的实现步骤:
1. 先配置Kestrel的两个独立端点
首先要在项目的配置阶段(比如.NET 6+的Program.cs,或者旧版本Startup.cs的ConfigureServices方法里)指定两个端口,分别对应MVC和gRPC,并设置对应的HTTP协议:
// .NET 6+ 风格的 Program.cs var builder = WebApplication.CreateBuilder(args); // 配置Kestrel的两个端点 builder.WebHost.ConfigureKestrel(options => { // MVC专属端点:localhost:8888,仅支持HTTP/1 options.ListenLocalhost(8888, listenOptions => { listenOptions.Protocols = HttpProtocols.Http1; }); // gRPC专属端点:localhost:8889,仅支持HTTP/2(gRPC必须依赖HTTP/2) options.ListenLocalhost(8889, listenOptions => { listenOptions.Protocols = HttpProtocols.Http2; }); }); // 注册必要服务 builder.Services.AddControllers(); builder.Services.AddGrpc(); var app = builder.Build();
2. 在UseEndpoints中添加条件映射
接下来修改你的端点配置逻辑,使用MapWhen方法根据请求的端口来区分映射MVC和gRPC服务,确保每个服务只会绑定到指定端口:
// 在Configure方法(或Program.cs的app配置段) app.UseRouting(); app.UseEndpoints(endpoints => { // 仅当请求来自8889端口时,映射gRPC服务 endpoints.MapWhen(context => context.Request.Host.Port == 8889, grpcEndpoints => { grpcEndpoints.MapGrpcService<ComunicacaoService>(); }); // 仅当请求来自8888端口时,映射MVC默认路由 endpoints.MapWhen(context => context.Request.Host.Port == 8888, mvcEndpoints => { mvcEndpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); }); }); app.Run();
原理说明
MapWhen方法会根据传入的条件判断,将请求路由到对应的端点集合中,实现了不同端口对应不同服务的隔离。- Kestrel的端点配置中明确指定了各自的HTTP协议,既满足gRPC对HTTP/2的强制要求,也符合MVC使用HTTP/1的需求。
这样配置完成后,localhost:8888只会响应MVC控制器的请求,localhost:8889只会处理gRPC调用,再也不会出现两个服务同时绑定到两个端口的情况啦!
内容的提问来源于stack exchange,提问作者Douglas Ramos




