Nguon: Microsoft Learn · .NET 8.0

gRPC-Web trong các ứng dụng ASP.NET Core gRPC

Nguồn: gRPC-Web in ASP.NET Core gRPC apps

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:

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:

csharp
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:

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.

csharp
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.

csharp
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:

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ế:

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:

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:

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:

csharp
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:

GrpcWebHandler có các tùy chọn cấu hình sau:

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:

csharp
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.