自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Golang 語言 gRPC 服務怎么同時支持 gRPC 和 HTTP 客戶端調(diào)用?

開發(fā) 前端
gRPC 客戶端服務的前提下,gRPC 服務端服務怎么同時支持 gRPC 和 HTTP 客戶端調(diào)用?今天我們介紹一個 protoc 插件 gRPC-Gateway。

01介紹

關于 gRPC 的文章,我們之前寫過幾篇,如果讀者朋友還對 gRPC 不了解,我建議您可以翻閱一下公眾號的歷史文章。

當我們需要提供 gRPC 服務的 RESTful API 時,可以先創(chuàng)建一個 gRPC 客戶端服務,在 gRPC 客戶端服務編寫 RESTful API,接收到 HTTP 請求時,通過 gRPC 客戶端服務調(diào)用 gRPC 服務端服務的方法。

相信讀者朋友們也意識到,僅僅為了提供 RESTful API 而編寫一個 gRPC 客戶端服務,顯然有些小題大做。

在不借助 gRPC 客戶端服務的前提下,gRPC 服務端服務怎么同時支持 gRPC 和 HTTP 客戶端調(diào)用?今天我們介紹一個 protoc 插件 gRPC-Gateway。

02gRPC-Gateway

gRPC-Gateway 是 protoc 的一個插件。它讀取 gRPC 服務定義并生成一個反向代理服務器,該服務器將 RESTful JSON API 轉換為 gRPC。此服務器是根據(jù) gRPC 定義中的自定義選項生成的。

gRPC-Gateway 可幫助您同時以 gRPC 和 RESTful 風格提供 API。

在我們開始編碼之前,需要一些先決條件。

首先,我們需要先搭建一個 Go 環(huán)境。

使用 go get 工具下載一些依賴包。

使用 go mod init 工具創(chuàng)建一個 go.mod 文件。

依賴包列表:

$ go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
$ go get google.golang.org/protobuf/cmd/protoc-gen-go
$ go get google.golang.org/grpc/cmd/protoc-gen-go-grpc

03gRPC-Gateway 實戰(zhàn)

在完成以上先決條件后,我們創(chuàng)建一個 gRPC 服務端服務,本文我們創(chuàng)建一個 ToDoList gRPC 服務。在創(chuàng)建 gRPC 服務之前,我們使用 protocol buffers 創(chuàng)建一個 proto 文件。

創(chuàng)建 proto 文件

...
service ToDoList {
rpc CreateToDoList (ToDoListDetail) returns (CreateToDoListResult) {}
rpc ReadToDoList (ToDoListPage) returns (ReadToDoListByPage) {}
}
...

生成 gRPC 服務端存根

使用 protoc 命令工具生成存根

protoc -I proto \
--go_out ./pb/todoPb --go_opt paths=source_relative \
--go-grpc_out ./pb/todoPb --go-grpc_opt paths=source_relative \
proto/toDoList.proto

執(zhí)行上面 protoc 命令工具,生成一個 *.pb.go 文件和一個 *_grpc.pb.go 文件。

編寫剩余 Go 代碼

創(chuàng)建 main.go

func main() {
InitEngine()
lis, err := net.Listen("tcp", address)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
server := grpc.NewServer()
pb.RegisterToDoListServer(server, new(service.ToDoList))
log.Printf("server listening at %v\n", lis.Addr())
if err := server.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}

添加 gRPC-Gateway 選項

gRPC-Gateway 使用 google.api.http 選項定義 gRPC 服務如何映射到 JSON 請求和響應,使用 protoc 時,每個 RPC 必須使用 google.api.http 選項定義 HTTP 方法和路徑。

因此,我們需要將 google/api/http.proto 導入添加到 proto 文件中。我們還需要添加我們想要的 HTTP -> gRPC 映射。

syntax = "proto3";

import "google/api/annotations.proto";

service ToDoList {
rpc CreateToDoList (ToDoListDetail) returns (CreateToDoListResult) {
option (google.api.http) = {
post: "/v1/todolist/add"
body: "*"
};
}
rpc ReadToDoList (ToDoListPage) returns (ReadToDoListByPage) {
option (google.api.http) = {
get: "/v1/todolist/select"
};
}
}
...

關于 HTTP 和 gRPC 映射的更多內(nèi)容,可以參閱 Google API 文檔。

生成 gRPC-Gateway 存根

現(xiàn)在,我們已將 gRPC-Gateway 選項添加到 proto 文件中,我們需要使用 gRPC-Gateway 生成器來生成存根。

在使用 protoc 生成存根之前,我們需要將一些依賴項復制到 proto 文件目錄中。將 googleapis 的子集從官方存儲庫下載并復制到本地 proto 文件目錄中。如下所示:

.
├── dao
│ ├── mysql.go
│ └── toDoList.go
├── grpc-gateway
│ └── main.go
├── main.go
├── pb
│ └── todoPb
│ ├── toDoList.pb.go
│ ├── toDoList.pb.gw.go
│ └── toDoList_grpc.pb.go
├── proto
│ ├── google
│ │ └── api
│ │ ├── annotations.proto
│ │ └── http.proto
│ └── toDoList.proto
└── service
└── toDoList.go

使用 protoc 生成存根

protoc -I proto \
--go_out ./pb/todoPb --go_opt paths=source_relative \
--go-grpc_out ./pb/todoPb --go-grpc_opt paths=source_relative \
--grpc-gateway_out ./pb/todoPb --grpc-gateway_opt paths=source_relative \
proto/toDoList.proto

protoc-go-inject-tag -XXX_skip=xorm -input=./pb/todoPb/toDoList.pb.go

執(zhí)行以上 protoc 命令工具,生成一個 *.gw.pb.go 文件。

創(chuàng)建 grpc-gateway 目錄,并創(chuàng)建 main.go 文件,創(chuàng)建 gRPC-Gateway 多路復用器。

func main() {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()

mux := runtime.NewServeMux()
opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
err := pb.RegisterToDoListHandlerFromEndpoint(ctx, mux, grpcServerEndpoint, opts)
if err != nil {
log.Fatalf("Fail to register gRPC gateway service endpoint: %v", err)
}

if err = http.ListenAndServe(":8080", mux); err != nil {
log.Fatalf("Could not setup HTTP endpoint: %v", err)
}
}

啟動服務

grpc 服務

go run main.go

gRPC-Gateway

go run grpc-gateway/main.go

cURL 測試

curl http://127.0.0.1:8080/v1/todolist/select?page=1&count=2

響應結果:

{
"todolist": [
{
"id": "1",
"content": "編程寫代碼",
"datetime": "1632541505",
"created": "1632541505",
"updated": "1632541505"
},
{
"id": "2",
"content": "編程寫代碼",
"datetime": "1632543373",
"created": "1632543373",
"updated": "1632543373"
}
]
}

04總結

本文我們介紹 gRPC-Gateway 如何實現(xiàn)同時支持 gRPC 和 RESTful 風格的 API。

當 HTTP 請求到達 gRPC-Gateway 時,它會將 JSON 數(shù)據(jù)解析為 protobuf 消息。然后,它使用解析的 protobuf 消息發(fā)出正常的 Go gRPC 客戶端請求。

Go gRPC 客戶端將 protobuf 結構編碼為 protobuf 二進制格式,并將其發(fā)送到 gRPC 服務器。gRPC 服務器處理請求并以 protobuf 二進制格式返回響應。

Go gRPC 客戶端將其解析為 protobuf 消息,并將其返回到 gRPC-Gateway,后者將 protobuf 消息編碼為 JSON 并將其返回到原始客戶端。

圖片來自 gRPC-Gateway 官方文檔


責任編輯:武曉燕 來源: Golang語言開發(fā)棧
相關推薦

2022-04-29 11:52:02

API代碼HTTP

2021-09-13 05:02:49

GogRPC語言

2021-10-18 05:00:38

語言GoRequestHTTP

2021-07-28 11:46:51

工具gRPC客戶端

2021-09-26 10:20:06

開發(fā)Golang代碼

2021-09-01 23:29:37

Golang語言gRPC

2022-01-05 08:03:23

C#通信Rest

2021-05-07 15:28:03

Kafka客戶端Sarama

2021-11-29 07:47:57

gRPCGUI客戶端

2025-01-13 06:00:00

Go語言gRPC

2025-02-04 13:53:18

NixGogRPC

2024-04-22 09:30:24

2023-03-28 07:03:15

gRPCMetadata

2023-03-02 07:20:10

GRPC服務健康檢查協(xié)議

2024-02-05 08:50:57

Golang標準庫客戶端

2023-06-10 23:01:41

GrpcProtobuf數(shù)據(jù)

2009-12-21 10:19:05

Silverlight

2021-10-26 09:26:21

編程技能開發(fā)

2023-03-05 23:11:07

Go語言服務

2023-09-06 07:17:57

點贊
收藏

51CTO技術棧公眾號