ASP.NET Core 中的 gRPC JSON 轉碼
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
gRPC 是高效能的遠端程序呼叫 (RPC) 架構。 gRPC 使用 HTTP/2、串流、Protobuf 和訊息合約來建立高效能、即時的服務。
gRPC 有一個限制是其並非適用於所有的平台。 瀏覽器並不完全支援 HTTP/2,這使得 REST API 和 JSON 成為將資料放入瀏覽器應用程式的主要方式。 儘管 gRPC 帶來的好處, REST API 和 JSON 在現代應用程式中占有重要地位。 建置 gRPC 和 JSON Web API 會為應用程式開發增加不必要的額外負荷。
本文件討論如何使用 gRPC 服務建立 JSON Web API。
概觀
gRPC JSON 轉碼是 ASP.NET Core 的擴充功能,可針對 gRPC 服務建立 RESTful JSON API。 設定之後,轉碼可讓應用程式使用熟悉的 HTTP 概念來呼叫 gRPC 服務:
- HTTP 指令動詞
- URL 參數繫結
- JSON 要求/回應
gRPC 仍可用來呼叫服務。
注意
gRPC JSON 轉碼取代 gRPC HTTP API,這是替代的實驗性擴充。
使用方式
在伺服器啟動程式碼中註冊轉碼,方法是新增
AddJsonTranscoding
:在Program.cs
檔案中,將builder.Services.AddGrpc();
變更為builder.Services.AddGrpc().AddJsonTranscoding();
。將
<IncludeHttpRuleProtos>true</IncludeHttpRuleProtos>
新增至專案檔 (.csproj
) 中的屬性群組:<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <InvariantGlobalization>true</InvariantGlobalization> <IncludeHttpRuleProtos>true</IncludeHttpRuleProtos> </PropertyGroup>
使用 HTTP 繫結和路由標註
.proto
檔案中的 gRPC 方法:syntax = "proto3"; option csharp_namespace = "GrpcServiceTranscoding"; import "google/api/annotations.proto"; package greet; // The greeting service definition. service Greeter { rpc SayHello (HelloRequest) returns (HelloReply) { option (google.api.http) = { get: "/v1/greeter/{name}" }; } } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings. message HelloReply { string message = 1; }
SayHello
gRPC 方法現在可以作為 gRPC 和 JSON Web API 呼叫:
- 要求:
GET /v1/greeter/world
- 回應︰
{ "message": "Hello world" }
如果伺服器設定為寫入每個要求的記錄,伺服器記錄會顯示 gRPC 服務會執行 HTTP 呼叫。 轉碼會將傳入 HTTP 要求對應至 gRPC 訊息,並將回應訊息轉換為 JSON。
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 1.996ms 200 application/json
標註 gRPC 方法
gRPC 方法必須以 HTTP 規則標註,才能支援轉碼。 HTTP 規則包含如何呼叫 gRPC 方法的相關資訊,例如 HTTP 方法和路由。
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
}
繼續範例:
- 使用
SayHello
方法定義Greeter
服務。 此方法具有使用名稱google.api.http
指定的 HTTP 規則。 - 可透過
GET
要求和/v1/greeter/{name}
路由來存取此方法。 - 要求訊息上的
name
欄位會繫結至路由參數。
有許多選項可用來自訂 gRPC 方法如何繫結至 RESTful API。 如需標註 gRPC 方法和自訂 JSON 的詳細資訊,請參閱 為 gPRC JSON 轉碼設定 HTTP 和 JSON。
串流方法
透過 HTTP/2 的傳統 gRPC 支援所有方向的串流。 轉碼僅限於伺服器串流。 不支援用戶端串流和雙向串流方法。
伺服器串流方法使用 以行分隔的 JSON。 使用 WriteAsync
撰寫的每個訊息都會序列化為 JSON,後面接著一新行。
下列伺服器串流方法會寫入三則訊息:
public override async Task StreamingFromServer(ExampleRequest request,
IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
for (var i = 1; i <= 3; i++)
{
await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
用戶端會收到三個以行分隔的 JSON 物件:
{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}
請注意, WriteIndented
JSON 設定無法套用至伺服器串流方法。 美化顯示會將新的行和空白字元新增至 JSON,這無法與以行分隔的 JSON 搭配使用。
檢視或下載 ASP.NET Core gPRC 轉碼和串流應用程式範例。
HTTP 通訊協定
包含在 .NET SDK 中的 ASP.NET Core gRPC 服務範本,會建立只針對 HTTP/2 設定的應用程式。 當應用程式僅支援透過 HTTP/2 的傳統 gRPC 時,HTTP/2 是很好的預設值。 不過,轉碼適用於 HTTP/1.1 和 HTTP/2。 某些平台,例如 UWP 或 Unity,無法使用 HTTP/2。 若要支援所有用戶端應用程式,請將伺服器設定為啟用 HTTP/1.1 和 HTTP/2。
更新 appsettings.json
中的預設通訊協定:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
在相同的連接埠上啟用 HTTP/1.1 和 HTTP/2 需要 TLS 進行通訊協定交涉。 如需在 gRPC 應用程式中設定 HTTP 通訊協定的詳細資訊,請參閱 ASP.NET Core gRPC 通訊協定交涉。
gRPC JSON 轉碼與 gRPC-Web
轉碼和 gRPC-Web 都允許從瀏覽器呼叫 gRPC 服務。 不過,每個執行這項操作的方式都不同:
- gRPC-Web 可讓瀏覽器應用程式使用 gRPC-Web 用戶端和 Protobuf 從瀏覽器呼叫 gRPC 服務。 gRPC-Web 需要瀏覽器應用程式產生 gRPC 用戶端,並具有快速傳送小型 Protobuf 訊息的優點。
- 轉碼可讓瀏覽器應用程式呼叫 gRPC 服務,就像是使用 JSON 的 RESTful API 一樣。 瀏覽器應用程式不需要產生 gRPC 用戶端或知道 gRPC 的任何資訊。
您可以使用瀏覽器 JavaScript API 來呼叫先前的 Greeter
服務:
var name = nameInput.value;
fetch('/v1/greeter/' + name)
.then((response) => response.json())
.then((result) => {
console.log(result.message);
// Hello world
});
grpc-gateway
grpc-gateway 是另一種從 gRPC 服務建立 RESTful JSON API 的技術。 grpc-gateway 使用相同的 .proto
註釋,將 HTTP 概念對應至 gRPC 服務。
grpc-gateway 會使用程式碼產生來建立反向 Proxy 伺服器。 反向 Proxy 會將 RESTful 呼叫轉譯成 gRPC+Protobuf,並透過 HTTP/2 將呼叫傳送至 gRPC 服務。 這種方法的優點是 gRPC 服務不知道 RESTful JSON API。 任何 gRPC 伺服器都可以使用 grpc-gateway。
同時,gRPC JSON 轉碼會在 ASP.NET Core 應用程式內執行, 可將 JSON 還原序列化為 Protobuf 訊息,然後直接叫用 gRPC 服務。 ASP.NET Core 中的轉碼為 .NET 應用程式開發人員提供許多優點:
- 較不複雜:gRPC 服務和對應的 RESTful JSON API 都是從一個 ASP.NET Core 應用程式開始執行。
- 更好的效能:將 JSON 轉碼還原序列化為 Protobuf 訊息,並直接叫用 gRPC 服務。 與對不同伺服器進行新的 gRPC 呼叫相比,在同處理序執行此動作具有顯著的效能優勢。
- 成本較低:伺服器越少,每月的裝載費用就越少。
如需 grpc-gateway 的安裝和使用方式,請參閱 grpc-gateway 讀我檔案。
其他資源
gRPC 是高效能的遠端程序呼叫 (RPC) 架構。 gRPC 使用 HTTP/2、串流、Protobuf 和訊息合約來建立高效能、即時的服務。
gRPC 有一個限制是其並非適用於所有的平台。 瀏覽器並不完全支援 HTTP/2,這使得 REST API 和 JSON 成為將資料放入瀏覽器應用程式的主要方式。 儘管 gRPC 帶來的好處, REST API 和 JSON 在現代應用程式中占有重要地位。 建置 gRPC 和 JSON Web API 會為應用程式開發增加不必要的額外負荷。
本文件討論如何使用 gRPC 服務建立 JSON Web API。
概觀
gRPC JSON 轉碼是 ASP.NET Core 的擴充功能,可針對 gRPC 服務建立 RESTful JSON API。 設定之後,轉碼可讓應用程式使用熟悉的 HTTP 概念來呼叫 gRPC 服務:
- HTTP 指令動詞
- URL 參數繫結
- JSON 要求/回應
gRPC 仍可用來呼叫服務。
注意
gRPC JSON 轉碼取代 gRPC HTTP API,這是替代的實驗性擴充。
使用方式
- 將套件參考新增至
Microsoft.AspNetCore.Grpc.JsonTranscoding
。 - 在伺服器啟動程式碼中註冊轉碼,方法是新增
AddJsonTranscoding
:在Program.cs
檔案中,將builder.Services.AddGrpc();
變更為builder.Services.AddGrpc().AddJsonTranscoding();
。 - 在包含
.csproj
檔案的專案目錄中建立目錄結構/google/api
。 - 將
google/api/http.proto
和google/api/annotations.proto
檔案新增至/google/api
目錄。 - 使用 HTTP 繫結和路由標註
.proto
檔案中的 gRPC 方法:
syntax = "proto3";
option csharp_namespace = "GrpcServiceTranscoding";
import "google/api/annotations.proto";
package greet;
// The greeting service definition.
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings.
message HelloReply {
string message = 1;
}
SayHello
gRPC 方法現在可以作為 gRPC 和 JSON Web API 呼叫:
- 要求:
GET /v1/greeter/world
- 回應︰
{ "message": "Hello world" }
如果伺服器設定為寫入每個要求的記錄,伺服器記錄會顯示 gRPC 服務會執行 HTTP 呼叫。 轉碼會將傳入 HTTP 要求對應至 gRPC 訊息,並將回應訊息轉換為 JSON。
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 GET https://localhost:5001/v1/greeter/world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'gRPC - /v1/greeter/{name}'
info: Server.GreeterService[0]
Sending hello to world
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'gRPC - /v1/greeter/{name}'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 1.996ms 200 application/json
標註 gRPC 方法
gRPC 方法必須以 HTTP 規則標註,才能支援轉碼。 HTTP 規則包含如何呼叫 gRPC 方法的相關資訊,例如 HTTP 方法和路由。
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
get: "/v1/greeter/{name}"
};
}
}
繼續範例:
- 使用
SayHello
方法定義Greeter
服務。 此方法具有使用名稱google.api.http
指定的 HTTP 規則。 - 可透過
GET
要求和/v1/greeter/{name}
路由來存取此方法。 - 要求訊息上的
name
欄位會繫結至路由參數。
有許多選項可用來自訂 gRPC 方法如何繫結至 RESTful API。 如需標註 gRPC 方法和自訂 JSON 的詳細資訊,請參閱 為 gPRC JSON 轉碼設定 HTTP 和 JSON。
串流方法
透過 HTTP/2 的傳統 gRPC 支援所有方向的串流。 轉碼僅限於伺服器串流。 不支援用戶端串流和雙向串流方法。
伺服器串流方法使用 以行分隔的 JSON。 使用 WriteAsync
撰寫的每個訊息都會序列化為 JSON,後面接著一新行。
下列伺服器串流方法會寫入三則訊息:
public override async Task StreamingFromServer(ExampleRequest request,
IServerStreamWriter<ExampleResponse> responseStream, ServerCallContext context)
{
for (var i = 1; i <= 3; i++)
{
await responseStream.WriteAsync(new ExampleResponse { Text = $"Message {i}" });
await Task.Delay(TimeSpan.FromSeconds(1));
}
}
用戶端會收到三個以行分隔的 JSON 物件:
{"Text":"Message 1"}
{"Text":"Message 2"}
{"Text":"Message 3"}
請注意, WriteIndented
JSON 設定無法套用至伺服器串流方法。 美化顯示會將新的行和空白字元新增至 JSON,這無法與以行分隔的 JSON 搭配使用。
檢視或下載 ASP.NET Core gPRC 轉碼和串流應用程式範例。
HTTP 通訊協定
包含在 .NET SDK 中的 ASP.NET Core gRPC 服務範本,會建立只針對 HTTP/2 設定的應用程式。 當應用程式僅支援透過 HTTP/2 的傳統 gRPC 時,HTTP/2 是很好的預設值。 不過,轉碼適用於 HTTP/1.1 和 HTTP/2。 某些平台,例如 UWP 或 Unity,無法使用 HTTP/2。 若要支援所有用戶端應用程式,請將伺服器設定為啟用 HTTP/1.1 和 HTTP/2。
更新 appsettings.json
中的預設通訊協定:
{
"Kestrel": {
"EndpointDefaults": {
"Protocols": "Http1AndHttp2"
}
}
}
在相同的連接埠上啟用 HTTP/1.1 和 HTTP/2 需要 TLS 進行通訊協定交涉。 如需在 gRPC 應用程式中設定 HTTP 通訊協定的詳細資訊,請參閱 ASP.NET Core gRPC 通訊協定交涉。
gRPC JSON 轉碼與 gRPC-Web
轉碼和 gRPC-Web 都允許從瀏覽器呼叫 gRPC 服務。 不過,每個執行這項操作的方式都不同:
- gRPC-Web 可讓瀏覽器應用程式使用 gRPC-Web 用戶端和 Protobuf 從瀏覽器呼叫 gRPC 服務。 gRPC-Web 需要瀏覽器應用程式產生 gRPC 用戶端,並具有快速傳送小型 Protobuf 訊息的優點。
- 轉碼可讓瀏覽器應用程式呼叫 gRPC 服務,就像是使用 JSON 的 RESTful API 一樣。 瀏覽器應用程式不需要產生 gRPC 用戶端或知道 gRPC 的任何資訊。
您可以使用瀏覽器 JavaScript API 來呼叫先前的 Greeter
服務:
var name = nameInput.value;
fetch('/v1/greeter/' + name)
.then((response) => response.json())
.then((result) => {
console.log(result.message);
// Hello world
});
grpc-gateway
grpc-gateway 是另一種從 gRPC 服務建立 RESTful JSON API 的技術。 grpc-gateway 使用相同的 .proto
註釋,將 HTTP 概念對應至 gRPC 服務。
grpc-gateway 會使用程式碼產生來建立反向 Proxy 伺服器。 反向 Proxy 會將 RESTful 呼叫轉譯成 gRPC+Protobuf,並透過 HTTP/2 將呼叫傳送至 gRPC 服務。 這種方法的優點是 gRPC 服務不知道 RESTful JSON API。 任何 gRPC 伺服器都可以使用 grpc-gateway。
同時,gRPC JSON 轉碼會在 ASP.NET Core 應用程式內執行, 可將 JSON 還原序列化為 Protobuf 訊息,然後直接叫用 gRPC 服務。 ASP.NET Core 中的轉碼為 .NET 應用程式開發人員提供許多優點:
- 較不複雜:gRPC 服務和對應的 RESTful JSON API 都是從一個 ASP.NET Core 應用程式開始執行。
- 更好的效能:將 JSON 轉碼還原序列化為 Protobuf 訊息,並直接叫用 gRPC 服務。 與對不同伺服器進行新的 gRPC 呼叫相比,在同處理序執行此動作具有顯著的效能優勢。
- 成本較低:伺服器越少,每月的裝載費用就越少。
如需 grpc-gateway 的安裝和使用方式,請參閱 grpc-gateway 讀我檔案。