在瀏覽器應用中使用 gRPC


 gRPC-Web 允許瀏覽器 JavaScript 和 Blazor 應用調用 gRPC 服務。 

有兩種方式可將 gRPC-Web 添加到 ASP.NET Core 應用中:

  • 在 ASP.NET Core 中同時支持 gRPC-Web 和 gRPC HTTP/2。 此選項會使用 Grpc.AspNetCore.Web 包提供的中間件。
  • 使用 Envoy 代理的 gRPC-Web 支持將 gRPC-Web 轉換為 gRPC HTTP/2。 轉換后的調用隨后會轉發給 ASP.NET Core 應用。

每種方法既有優點,也有缺點。 如果應用的環境已將 Envoy 用作代理,則也可以使用 Envoy 提供 gRPC-Web 支持。 對於僅需要 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();
    });
}

或者,可以配置 gRPC-Web 中間件,使所有服務在默認情況下都支持 gRPC-Web,而不需要 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

瀏覽器安全性可防止網頁向不處理網頁的域發送請求。 此限制適用於使用瀏覽器應用發出 gRPC-Web 調用。 例如,由 https://www.contoso.com 提供服務的瀏覽器應用對托管於 https://services.contoso.com 上的 gRPC-Web 服務的調用會被阻止。 跨域資源共享 (CORS) 可用於放寬此限制。

若要允許瀏覽器應用進行跨域 gRPC-Web 調用,請在 ASP.NET Core 中設置 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 和流式處理

HTTP/2 上的傳統 gRPC 支持所有方向的流式處理。 gRPC-Web 對流式處理提供有限的支持:

  • gRPC-Web 瀏覽器客戶端不支持調用客戶端流式處理和雙向流式處理方法。
  • 托管在 Azure 應用服務和 IIS 上的 ASP.NET Core gRPC 服務不支持雙向流式處理。

使用 gRPC 時,僅建議使用一元方法和服務器流式處理方法。

 

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

可以將 .NET gRPC 客戶端配置為發出 gRPC-Web 調用。 這對於托管在瀏覽器中且具有相同 JavaScript 代碼 HTTP 限制的 Blazor WebAssembly 應用來說非常有用。 使用 .NET 客戶端調用 gRPC-Web 與 HTTP/2 gRPC 相同。 唯一的修改是創建通道的方式。

var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
    {
        HttpHandler = new GrpcWebHandler(new HttpClientHandler())
    });

GrpcWebHandler 具有以下配置選項:

  • InnerHandler:發出 gRPC HTTP 請求的基礎 HttpMessageHandler,例如 HttpClientHandler
  • GrpcWebMode:枚舉類型,指定 gRPC HTTP 請求 Content-Type 是 application/grpc-web 還是 application/grpc-web-text
    • GrpcWebMode.GrpcWeb 配置不進行編碼即發送的內容。 默認值。
    • GrpcWebMode.GrpcWebText 配置需進行 base64 編碼的內容。 對於瀏覽器中的服務器流式處理調用是必需的。
  • HttpVersion:HTTP 協議 Version 用於在基礎 gRPC HTTP 請求上設置 HttpRequestMessage.Version。 gRPC-Web 不需要特定版本,且除非指定,否則不會替代默認版本。

生成的 gRPC 客戶端具有用於調用一元方法的同步和異步方法。 例如,SayHello 是同步的,而 SayHelloAsync 是異步的。 在 Blazor WebAssembly 應用中調用同步方法將導致應用無響應。 必須始終在 Blazor WebAssembly 中使用異步方法。

 

將 gRPC-Web 與 gRPC 客戶端工廠一起使用

可以使用 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 是為 gRPC 服務創建 RESTful JSON API 的 ASP.NET Core 的實驗性擴展。 配置 gRPC HTTP API 后,應用可以使用熟悉的 HTTP 概念調用 gRPC 服務:

  1. 將包引用添加到 Microsoft.AspNetCore.Grpc.HttpApi
  2. 使用 AddGrpcHttpApi 在 Startup.cs 中注冊服務。
  3. 將 google/api/http.proto 和 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 HTTP API 和 gRPC-Web 都支持從瀏覽器調用 gRPC 服務。 但是,它們的操作方式是不同的:

  • gRPC-Web 允許瀏覽器應用通過 gRPC-Web 客戶端和 Protobuf 從瀏覽器調用 gRPC 服務。 gRPC-Web 需要瀏覽器應用生成 gRPC 客戶端,並且具有快速發送小型 Protobuf 消息的優點。
  • gRPC HTTP API 允許瀏覽器應用調用 gRPC 服務,就像它們是使用 JSON 的 RESTful API 一樣。 瀏覽器應用不需要生成 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

Grpc-gateway 是從 grpc 服務創建 RESTful JSON API 的另一種技術。 它使用相同的 .proto 注釋將 HTTP 概念映射到 gRPC 服務。

Grpc-gateway 和 gRPC HTTP API 最大的區別是 grpc-gateway 使用代碼生成來創建反向代理服務器。 反向代理將 RESTful 調用轉換為 gRPC,然后將它們發送到 gRPC 服務。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM