gRPC-Web trong các ứng dụng ASP.NET Core gRPC
Tìm hiểu cách cấu hình một ASP.NET Core gRPC service hiện có để có thể gọi từ các ứng dụng trình duyệt, sử dụng giao thức gRPC-Web. gRPC-Web cho phép các ứng dụng JavaScript trình duyệt và Blazor gọi gRPC services. Không thể gọi một HTTP/2 gRPC service từ ứng dụng dựa trên trình duyệt. Các gRPC services được hosted trong ASP.NET Core có thể được cấu hình để hỗ trợ gRPC-Web cùng với HTTP/2 gRPC.
Để biết hướng dẫn thêm gRPC service vào ứng dụng ASP.NET Core hiện có, xem Add gRPC services to an ASP.NET Core app.
Để biết hướng dẫn tạo gRPC project, xem Create a .NET gRPC client and server in ASP.NET Core.
ASP.NET Core gRPC-Web so với Envoy
Có hai lựa chọn để thêm gRPC-Web vào ứng dụng ASP.NET Core:
- Hỗ trợ gRPC-Web cùng với gRPC HTTP/2 trong ASP.NET Core. Tùy chọn này sử dụng middleware (phần mềm trung gian) được cung cấp bởi package
Grpc.AspNetCore.Web. - Sử dụng hỗ trợ gRPC-Web của Envoy proxy để chuyển đổi gRPC-Web sang gRPC HTTP/2. Cuộc gọi được chuyển đổi sau đó được chuyển tiếp đến ứng dụng ASP.NET Core.
Mỗi cách tiếp cận đều có ưu và nhược điểm. Nếu môi trường của ứng dụng đã sử dụng Envoy làm proxy, có thể hợp lý khi cũng sử dụng Envoy để cung cấp hỗ trợ gRPC-Web. Đối với giải pháp cơ bản cho gRPC-Web chỉ yêu cầu ASP.NET Core, Grpc.AspNetCore.Web là lựa chọn tốt.
Cấu hình gRPC-Web trong ASP.NET Core
Các gRPC services được hosted trong ASP.NET Core có thể được cấu hình để hỗ trợ gRPC-Web cùng với HTTP/2 gRPC. gRPC-Web không yêu cầu bất kỳ thay đổi nào đối với services. Sửa đổi duy nhất là trong cài đặt middleware trong Program.cs.
Để bật gRPC-Web với ASP.NET Core gRPC service:
- Thêm tham chiếu đến package
Grpc.AspNetCore.Web. - Cấu hình ứng dụng để sử dụng gRPC-Web bằng cách thêm
UseGrpcWebvàEnableGrpcWebvàoProgram.cs:
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.UseGrpcWeb();
app.MapGrpcService<GreeterService>().EnableGrpcWeb();
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled and is " +
"callable from browser apps using the gRPC-Web protocol");
app.Run();Code trên:
- Thêm gRPC-Web middleware,
UseGrpcWeb, sau routing và trước endpoints. - Chỉ định rằng phương thức
endpoints.MapGrpcService<GreeterService>()hỗ trợ gRPC-Web vớiEnableGrpcWeb.
Ngoài ra, gRPC-Web middleware có thể được cấu hình để tất cả các services đều hỗ trợ gRPC-Web theo mặc định và không cần EnableGrpcWeb. Chỉ định new GrpcWebOptions { DefaultEnabled = true } khi thêm middleware.
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.MapGrpcService<GreeterService>();
app.MapGet("/", () => "All gRPC service are supported by default in " +
"this example, and are callable from browser apps using the " +
"gRPC-Web protocol");
app.Run();Lưu ý: Có một vấn đề đã biết khiến gRPC-Web thất bại khi được hosted bởi HTTP.sys trong .NET Core 3.x.
Cách khắc phục để gRPC-Web hoạt động trên HTTP.sys có trong Grpc-web experimental and UseHttpSys()? (grpc/grpc-dotnet #853).
gRPC-Web và CORS
Bảo mật trình duyệt ngăn chặn các trang web thực hiện các request đến domain khác với domain phục vụ trang web. Hạn chế này áp dụng cho việc thực hiện các cuộc gọi gRPC-Web với ứng dụng trình duyệt. Ví dụ: ứng dụng trình duyệt được phục vụ bởi https://www.contoso.com bị chặn không cho gọi các gRPC-Web services được hosted trên https://services.contoso.com. Cross-Origin Resource Sharing (CORS - Chia sẻ tài nguyên có nguồn gốc chéo) có thể được sử dụng để nới lỏng hạn chế này.
Để cho phép ứng dụng trình duyệt thực hiện các cuộc gọi gRPC-Web cross-origin, thiết lập CORS trong ASP.NET Core. Sử dụng hỗ trợ CORS tích hợp sẵn và expose các header đặc thù của gRPC với WithExposedHeaders.
using GrpcGreeter.Services;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
builder.Services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Grpc-Status", "Grpc-Message",
"Grpc-Encoding", "Grpc-Accept-Encoding",
"Grpc-Status-Details-Bin");
}));
var app = builder.Build();
app.UseGrpcWeb();
app.UseCors();
app.MapGrpcService<GreeterService>().EnableGrpcWeb()
.RequireCors("AllowAll");
app.MapGet("/", () => "This gRPC service is gRPC-Web enabled, CORS " +
"enabled, and is callable from browser apps using the gRPC-Web " +
"protocol");
app.Run();Code trên:
- Gọi
AddCorsđể thêm CORS services và cấu hình CORS policy expose các header đặc thù của gRPC. - Gọi
UseCorsđể thêm CORS middleware sau cấu hình routing và trước cấu hình endpoints. - Chỉ định rằng phương thức
endpoints.MapGrpcService<GreeterService>()hỗ trợ CORS vớiRequireCors.
gRPC-Web và streaming (luồng dữ liệu)
gRPC truyền thống qua HTTP/2 hỗ trợ client streaming, server streaming và bidirectional streaming. gRPC-Web cung cấp hỗ trợ streaming hạn chế:
- gRPC-Web browser client không hỗ trợ gọi các phương thức client streaming và bidirectional streaming.
- gRPC-Web .NET client không hỗ trợ gọi các phương thức client streaming và bidirectional streaming qua HTTP/1.1.
- Các ASP.NET Core gRPC services được hosted trên Azure App Service và IIS không hỗ trợ bidirectional streaming.
Khi sử dụng gRPC-Web, chúng tôi chỉ khuyến nghị sử dụng các unary method (phương thức đơn chiều) và server streaming method.
Giao thức HTTP
Template ASP.NET Core gRPC service, được bao gồm trong .NET SDK, tạo ứng dụng chỉ được cấu hình cho HTTP/2. Đây là mặc định tốt khi ứng dụng chỉ hỗ trợ gRPC truyền thống qua HTTP/2. Tuy nhiên, gRPC-Web hoạt động với cả HTTP/1.1 và HTTP/2. Một số nền tảng, chẳng hạn như UWP hoặc Unity, không thể sử dụng HTTP/2. Để hỗ trợ tất cả các ứng dụng client, hãy cấu hình server để bật HTTP/1.1 và HTTP/2.
Cập nhật giao thức mặc định trong appsettings.json:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}Ngoài ra, cấu hình Kestrel endpoints trong startup code.
Bật HTTP/1.1 và HTTP/2 trên cùng một cổng yêu cầu TLS để thương lượng giao thức. Để biết thêm thông tin, xem ASP.NET Core gRPC protocol negotiation.
Gọi gRPC-Web từ trình duyệt
Các ứng dụng trình duyệt có thể sử dụng gRPC-Web để gọi gRPC services. Có một số yêu cầu và hạn chế khi gọi gRPC services với gRPC-Web từ trình duyệt:
- Server phải chứa cấu hình để hỗ trợ gRPC-Web.
- Các cuộc gọi client streaming và bidirectional streaming không được hỗ trợ. Server streaming được hỗ trợ.
- Gọi gRPC services trên domain khác yêu cầu cấu hình CORS trên server.
JavaScript gRPC-Web client
Có một JavaScript gRPC-Web client. Để biết hướng dẫn về cách sử dụng gRPC-Web từ JavaScript, xem write JavaScript client code with gRPC-Web.
Cấu hình gRPC-Web với .NET gRPC client
.NET gRPC client có thể được cấu hình để thực hiện các cuộc gọi gRPC-Web. Điều này hữu ích cho các ứng dụng Blazor WebAssembly, được hosted trong trình duyệt và có cùng các giới hạn HTTP của JavaScript code. Gọi gRPC-Web với .NET client giống như HTTP/2 gRPC. Sửa đổi duy nhất là cách tạo channel.
Để sử dụng gRPC-Web:
- Thêm tham chiếu đến package
Grpc.Net.Client.Web. - Đảm bảo tham chiếu đến package
Grpc.Net.Clientlà phiên bản 2.29.0 trở lên. - Cấu hình channel để sử dụng
GrpcWebHandler:
var channel = GrpcChannel.ForAddress("https://localhost:53305", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
new HelloRequest { Name = "GreeterClient" });Code trên:
- Cấu hình channel để sử dụng gRPC-Web.
- Tạo client và thực hiện cuộc gọi sử dụng channel.
GrpcWebHandler có các tùy chọn cấu hình sau:
InnerHandler: HttpMessageHandler cơ bản thực hiện gRPC HTTP request, ví dụ:HttpClientHandler.GrpcWebMode: Kiểu enum chỉ định liệuContent-Typecủa gRPC HTTP request làapplication/grpc-webhayapplication/grpc-web-text.GrpcWebMode.GrpcWebcấu hình gửi nội dung không mã hóa. Giá trị mặc định.GrpcWebMode.GrpcWebTextcấu hình nội dung mã hóa base64. Bắt buộc đối với các cuộc gọi server streaming trong trình duyệt.GrpcChannelOptions.HttpVersionvàGrpcChannelOptions.HttpVersionPolicycó thể được sử dụng để cấu hình phiên bản giao thức HTTP.
Quan trọng: Các gRPC client được tạo ra có các phương thức đồng bộ và bất đồng bộ để gọi các unary method. Ví dụ: SayHello là đồng bộ, và SayHelloAsync là bất đồng bộ. Các phương thức bất đồng bộ luôn được yêu cầu trong Blazor WebAssembly. Gọi phương thức đồng bộ trong ứng dụng Blazor WebAssembly khiến ứng dụng không phản hồi.
Sử dụng gRPC client factory với gRPC-Web
Tạo .NET client tương thích với gRPC-Web bằng cách sử dụng gRPC client factory:
- Thêm các tham chiếu package vào project file cho các package sau:
Grpc.Net.Client.WebGrpc.Net.ClientFactory- Đăng ký gRPC client với dependency injection (DI) sử dụng extension method generic
AddGrpcClient. Trong ứng dụng Blazor WebAssembly, các services được đăng ký với DI trongProgram.cs. - Cấu hình
GrpcWebHandlersử dụng extension method ConfigurePrimaryHttpMessageHandler.
builder.Services
.AddGrpcClient<Greet.GreeterClient>(options =>
{
options.Address = new Uri("https://localhost:5001");
})
.ConfigurePrimaryHttpMessageHandler(
() => new GrpcWebHandler(new HttpClientHandler()));Để biết thêm thông tin, xem gRPC client factory integration in .NET.