ASP.NET Core: gRPC-Web trong ứng dụng gRPC ASP.NET Core
Sử dụng gRPC trong ứng dụng trình duyệt
Không thể gọi trực tiếp dịch vụ gRPC từ trình duyệt. gRPC sử dụng các tính năng HTTP/2 và không có trình duyệt nào cung cấp mức độ kiểm soát cần thiết đối với các yêu cầu web để hỗ trợ máy khách gRPC.
gRPC trên ASP.NET Core cung cấp hai giải pháp tương thích với trình duyệt là gRPC-Web và chuyển mã JSON gRPC.
gRPC-Web
gRPC-Web cho phép các ứng dụng trình duyệt gọi các dịch vụ gRPC bằng ứng dụng khách gRPC-Web và Protobuf.
- Tương tự như gRPC thông thường, nhưng nó có giao thức dây (wire) hơi khác một chút, giúp nó tương thích với HTTP/1.1 và các trình duyệt.
- Yêu cầu ứng dụng trình duyệt tạo ứng dụng khách gRPC từ một file
.proto
. - Cho phép các ứng dụng trình duyệt được hưởng lợi từ việc sử dụng tin message phân ở mức hiệu suất cao và mạng thấp.
.NET có hỗ trợ tích hợp cho gRPC-Web. Để biết thêm thông tin, hãy xem gRPC-Web trong ứng dụng gRPC ASP.NET Core.
Chuyển mã JSON gRPC
Chuyển mã JSON gRPC cho phép các ứng dụng trình duyệt gọi các dịch vụ gRPC như thể chúng là các API RESTful có JSON.
- Ứng dụng trình duyệt không cần tạo ứng dụng khách gRPC hoặc biết bất kỳ điều gì về gRPC.
- API RESTful được tạo tự động từ các dịch vụ gRPC bằng cách chú thích file
.proto
bằng siêu dữ liệu HTTP. - Cho phép ứng dụng hỗ trợ cả API web gRPC và JSON mà không cần nỗ lực xây dựng các dịch vụ riêng biệt cho cả hai.
.NET có hỗ trợ tích hợp để tạo API web JSON từ các dịch vụ gRPC. Để biết thêm thông tin, hãy xem Chuyển mã JSON gRPC trong ứng dụng gRPC ASP.NET Core.
Ghi chú
Chuyển mã JSON gRPC yêu cầu .NET 7 trở lên.
Trong bài viết này
- ASP.NET Core gRPC-Web so với Envoy
- Định cấu hình gRPC-Web trong ASP.NET Core
- Gọi gRPC-Web từ trình duyệt
- Tài nguyên bổ sung
Tìm hiểu cách định cấu hình dịch vụ gRPC ASP.NET Core hiện có để có thể gọi được 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 và Blazor của trình duyệt gọi các dịch vụ gRPC. Không thể gọi dịch vụ gRPC HTTP/2 từ ứng dụng dựa trên trình duyệt. Các dịch vụ gRPC được lưu trữ 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 về cách thêm dịch vụ gRPC vào ứng dụng ASP.NET Core hiện có, hãy xem Thêm dịch vụ gRPC vào ứng dụng ASP.NET Core.
Để biết hướng dẫn về cách tạo dự án gRPC, hãy xem Tạo máy khách và máy chủ gRPC .NET Core trong ASP.NET Core.
ASP.NET Core gRPC-Web so với Envoy
Có hai lựa chọn về cách 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 do gói Grpc.AspNetCore.Web cung cấp.
- Sử dụng hỗ trợ gRPC-Web của proxy Envoy để dịch gRPC-Web sang gRPC HTTP/2. Lời gọi đã dịch sau đó sẽ được chuyển tiếp tới ứng dụng ASP.NET Core.
Có những ưu và nhược điểm đối với mỗi cách tiếp cận. Nếu môi trường của ứng dụng đã sử dụng Envoy làm proxy thì bạn cũng có thể sử dụng Envoy để cung cấp hỗ trợ gRPC-Web. Đối với một giải pháp cơ bản cho gRPC-Web chỉ yêu cầu ASP.NET Core, Grpc.AspNetCore.Web
là một lựa chọn tốt.
Định cấu hình gRPC-Web trong ASP.NET Core
Các dịch vụ gRPC được lưu trữ 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 dịch vụ. Sửa đổi duy nhất là cấu hình khởi động.
Để kích hoạt gRPC-Web bằng dịch vụ gRPC ASP.NET Core:
- Thêm một tham chiếu đến gói Grpc.AspNetCore.Web.
- Định cấu hình ứng dụng để sử dụng gRPC-Web bằng cách thêm
UseGrpcWeb
vàEnableGrpcWeb
vàoStartup.cs
:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb(); // Phải được thêm vào giữa UseRouting và UseEndpoints
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb();
});
}
Đoạn code trên:
- Thêm middleware gRPC-Web,
UseGrpcWeb
sau khi định tuyến và trước các điểm cuối (endpoint). - Chỉ định rằng phương thức
endpoints.MapGrpcService<GreeterService>()
hỗ trợ gRPC-Web vớiEnableGrpcWeb
.
Ngoài ra, middleware gRPC-Web có thể được định cấu hình để tất cả các dịch vụ đều hỗ trợ gRPC-Web theo mặc định và EnableGrpcWeb
không bắt buộc. Chỉ định new GrpcWebOptions { DefaultEnabled = true }
khi middleware được thêm vào.
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
});
}
}
Ghi chú
Có một sự cố đã biết khiến gRPC-Web không thành công khi được lưu trữ bởi HTTP.sys trong .NET Core 3.x.
Giải pháp thay thế để gRPC-Web hoạt động trên HTTP.sys có sẵn trong Grpc-web thử nghiệm và UseHttpSys() không? (grpc/grpc-dotnet #853).
gRPC-Web và CORS
Bảo mật trình duyệt ngăn trang web thực hiện yêu cầu tới một miền khác với miền phục vụ trang web đó. Hạn chế này áp dụng cho việc thực hiện lệnh gọi gRPC-Web bằng ứng dụng trình duyệt. Ví dụ: một ứng dụng trình duyệt do nó cung cấp https://www.contoso.com
bị chặn gọi các dịch vụ gRPC-Web được lưu trữ trên https://services.contoso.com
. Chia sẻ tài nguyên giữa các nguồn gốc (Cross-Origin Resource Sharing - CORS) 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 lệnh gọi gRPC-Web có nguồn gốc chéo, hãy thiết lập CORS trong ASP.NET Core. Sử dụng hỗ trợ CORS tích hợp và hiển thị các header dành riêng cho gRPC với WithExposeHeaders.
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
services.AddCors(o => o.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader()
.WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
}));
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseGrpcWeb();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb()
.RequireCors("AllowAll");
});
}
Đoạn code trên:
- Các lệnh gọi
AddCors
để thêm dịch vụ CORS và định cấu hình chính sách CORS hiển thị các header dành riêng cho gRPC. - Các lệnh gọi
UseCors
để thêm middleware CORS sau cấu hình định tuyến và trước cấu hình điểm cuối. - Chỉ định rằng phương thức
endpoints.MapGrpcService<GreeterService>()
hỗ trợ CORS vớiRequireCors
.
gRPC-Web và truyền phát (streaming)
gRPC truyền thống qua HTTP/2 hỗ trợ các phương thức truyền phát máy khách, máy chủ và hai chiều, còn gRPC-Web cung cấp hỗ trợ hạn chế cho truyền phát:
- Ứng dụng khách trình duyệt gRPC-Web không hỗ trợ các phương thức truyền phát ứng dụng khách và truyền phát hai chiều.
- Máy khách gRPC-Web .NET không hỗ trợ gọi các phương thức truyền phát ứng dụng khách và truyền phát hai chiều qua HTTP/1.1.
- Các dịch vụ gRPC của ASP.NET Core được lưu trữ trên Azure App Service và IIS không hỗ trợ truyền phát hai chiều.
Khi sử dụng gRPC-Web, ta nên sử dụng các phương thức truyền phát đơn nhất và truyền phát máy chủ.
Giao thức HTTP
Mẫu dịch vụ gRPC ASP.NET Core, có trong .NET SDK, tạo ra một ứng dụng chỉ được định cấu hình cho HTTP/2. Đây là một mặc định phù hợp khi một ứ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 khách, hãy định cấu hình máy chủ để 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, hãy định cấu hình điểm cuối Kestrel trong code startup.
Việc bật HTTP/1.1 và HTTP/2 trên cùng một cổng yêu cầu TLS để đàm phán giao thức. Để biết thêm thông tin, hãy xem Đàm phán giao thức gRPC của ASP.NET Core.
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 các dịch vụ gRPC. Có một số yêu cầu và hạn chế khi gọi dịch vụ gRPC bằng gRPC-Web từ trình duyệt:
- Máy chủ phải chứa cấu hình để hỗ trợ gRPC-Web.
- Truyền phát ứng dụng khách và lời gọi truyền phát hai chiều không được hỗ trợ. Truyền phát máy chủ được hỗ trợ.
- Việc gọi các dịch vụ gRPC trên một miền khác yêu cầu cấu hình CORS trên máy chủ.
Máy khách gRPC-Web JavaScript
Đã tồn tại một ứng dụng khách gRPC-Web JavaScript. Để biết hướng dẫn về cách sử dụng gRPC-Web từ JavaScript, hãy xem viết mã máy khách JavaScript bằng gRPC-Web.
Định cấu hình gRPC-Web với máy khách .NET gRPC
Máy khách .NET gRPC có thể được cấu hình để thực hiện các lời gọi gRPC-Web. Điều này hữu ích cho các ứng dụng Blazor WebAssugging, được lưu trữ trong trình duyệt và có cùng giới hạn HTTP của mã JavaScript. Gọi gRPC-Web bằng máy khách .NET cũng giống như HTTP/2 gRPC. Sửa đổi duy nhất là cách tạo kênh.
Để sử dụng gRPC-Web:
- Thêm một tham chiếu đến gói Grpc.Net.Client.Web.
- Đảm bảo tham chiếu đến gói Grpc.Net.Client là phiên bản 2.29.0 trở lên.
- Định cấu hình kênh để sử dụng
GrpcWebHandler
:
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(new HttpClientHandler())
});
var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = ".NET" });
Đoạn code trên:
- Định cấu hình kênh để sử dụng gRPC-Web.
- Tạo một ứng dụng khách và thực hiện lời gọi bằng kênh.
GrpcWebHandler
có các tùy chọn cấu hình sau:
InnerHandler
: HttpMessageHandler cơ bản tạo ra yêu cầu HTTP gRPC, chẳng hạn nhưHttpClientHandler
.GrpcWebMode
: Kiểu liệt kê chỉ định xem yêu cầu HTTP gRPCContent-Type
làapplication/grpc-web
hayapplication/grpc-web-text
.GrpcWebMode.GrpcWeb
định cấu hình gửi nội dung mà không cần mã hóa. Giá trị là mặc định.GrpcWebMode.GrpcWebText
định cấu hình nội dung được mã hóa base64. Cần thiết cho các lời gọi truyền phát máy chủ trong trình duyệt.
HttpVersion
: Giao thức HTTPVersion
được sử dụng để đặt HttpRequestMessage.Version trên yêu cầu HTTP gRPC cơ bản. gRPC-Web không yêu cầu phiên bản cụ thể và không ghi đè phiên bản mặc định trừ khi được chỉ định.
Quan trọng
Các máy khách gRPC được tạo có các phương thức đồng bộ và không đồng bộ để gọi các phương thức đơn nhất. Ví dụ:
SayHello
là đồng bộ vàSayHelloAsync
là không đồng bộ. Các phương thức không đồng bộ luôn được yêu cầu trong Blazor WebAssugging. Việc gọi một phương thức đồng bộ trong ứng dụng Blazor WebAssugging khiến ứng dụng không phản hồi.
Sử dụng factory máy khách gRPC với gRPC-Web
Tạo một máy khách .NET tương thích với gRPC-Web bằng cách sử dụng factory máy máy khách gRPC:
- Thêm tham chiếu gói vào file dự án cho các gói sau:
- Đăng ký máy khách gRPC với tính năng chèn phụ thuộc (DI) bằng phương thức mở rộng generic
AddGrpcClient
. Trong ứng dụng Blazor WebAssugging, các dịch vụ được đăng ký với DI ở định dạngProgram.cs
. - Định cấu hình
GrpcWebHandler
bằng phương thức tiện ích mở rộng 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, hãy xem tích hợp factory máy khách gRPC trong .NET.
Tài nguyên bổ sung
- gRPC cho dự án GitHub của máy khách web
- Kích hoạt yêu cầu nguồn gốc chéo (CORS) trong ASP.NET Core
- Chuyển mã JSON gRPC trong ứng dụng gRPC ASP.NET Core