gRPC-Web 允许浏览器 JavaScript 和 Blazor 应用调用 gRPC 服务。 

有两种方式可将 gRPC-Web 添加到 ASP.NET Core 应用中:

  • 此选项会使用 Grpc.AspNetCore.Web 包提供的中间件。
  • 转换后的调用随后会转发给 ASP.NET Core 应用。

对于仅需要 ASP.NET Core 的 gRPC-Web 的基本解决方案,Grpc.AspNetCore.Web 是一个不错的选择。

 

若要使用 ASP.NET Core gRPC 服务启用 gRPC-Web:

  • Grpc.AspNetCore.Web 包的引用。
  • 配置应用以使用 gRPC-Web,方法是将 UseGrpcWeb 和 EnableGrpcWeb 添加到 Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpc();
}

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();

    app.UseGrpcWeb(); // Must be added between UseRouting and UseEndpoints

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>().EnableGrpcWeb();
    });
}

在添加中间件时指定 new GrpcWebOptions { DefaultEnabled = true }

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>();
        });
    }
}

 

gRPC-Web 和 CORS

跨域资源共享 (CORS) 可用于放宽此限制。

WithExposedHeaders 公开特定于 gRPC 的标头。

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");
    });
}

 

gRPC-Web 和流式处理

gRPC-Web 对流式处理提供有限的支持:

  • gRPC-Web 浏览器客户端不支持调用客户端流式处理和双向流式处理方法。
  • 托管在 Azure 应用服务和 IIS 上的 ASP.NET Core gRPC 服务不支持双向流式处理。

使用 gRPC 时,仅建议使用一元方法和服务器流式处理方法。

 

使用 .NET gRPC 客户端配置 gRPC-Web

唯一的修改是创建通道的方式。

  • Grpc.Net.Client.Web 包的引用。
  • Grpc.Net.Client 包的引用为 2.29.0 或更高版本。
  • 配置通道以使用 GrpcWebHandler
var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
    {
        HttpHandler = new GrpcWebHandler(new HttpClientHandler())
    });

GrpcWebHandler 具有以下配置选项:

  • HttpMessageHandler,例如 HttpClientHandler
  • GrpcWebMode:枚举类型,指定 gRPC HTTP 请求 Content-Type 是 application/grpc-web 还是 application/grpc-web-text
    • 默认值。
    • 对于浏览器中的服务器流式处理调用是必需的。
  • gRPC-Web 不需要特定版本,且除非指定,否则不会替代默认版本。

必须始终在 Blazor WebAssembly 中使用异步方法。

 

将 gRPC-Web 与 gRPC 客户端工厂一起使用

HttpClientFactory 的集成来创建与 gRPC-Web 兼容的 .NET 客户端。

builder.Services
    .AddGrpcClient<Greet.GreeterClient>((services, options) =>
    {
        options.Address = new Uri("https://localhost:5001");
    })
    .ConfigurePrimaryHttpMessageHandler(
        () => new GrpcWebHandler(GrpcWebMode.GrpcWebText, new HttpClientHandler()));

 

gRPC HTTP API

配置 gRPC HTTP API 后,应用可以使用熟悉的 HTTP 概念调用 gRPC 服务:

  1. Microsoft.AspNetCore.Grpc.HttpApi。
  2. 使用 AddGrpcHttpApi 在 Startup.cs 中注册服务。
  3. google/api/annotations.proto 文件添加到你的项目。
  4. 用 HTTP 绑定和路由在 .proto 文件中注释 gRPC 方法:
syntax = "proto3";

import "google/api/annotations.proto";

package greet;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      get: "v1/greeter/{name}"
    };
  }
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

 gRPC HTTP API 将传入的 HTTP 请求映射到 gRPC 消息,然后将响应消息转换为 JSON。

 

gRPC HTTP API 与 gRPC-Web

但是,它们的操作方式是不同的:

  • gRPC-Web 需要浏览器应用生成 gRPC 客户端,并且具有快速发送小型 Protobuf 消息的优点。
  • 浏览器应用不需要生成 gRPC 客户端或了解 gRPC 的任何信息。
var name = nameInput.value;

fetch("/v1/greeter/" + name).then(function (response) {
  response.json().then(function (data) {
    console.log("Result: " + data.message);
  });
});

 

grpc-gateway

它使用相同的 .proto 注释将 HTTP 概念映射到 gRPC 服务。

反向代理将 RESTful 调用转换为 gRPC,然后将它们发送到 gRPC 服务。

 

 

相关文章: