偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

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

01介紹

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

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

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

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

02gRPC-Gateway

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

gRPC-Gateway 可幫助您同時以 gRPC 和 RESTful 風(fēng)格提供 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 服務(wù)端服務(wù),本文我們創(chuàng)建一個 ToDoList gRPC 服務(wù)。在創(chuàng)建 gRPC 服務(wù)之前,我們使用 protocol buffers 創(chuàng)建一個 proto 文件。

創(chuàng)建 proto 文件

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

生成 gRPC 服務(wù)端存根

使用 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 服務(wù)如何映射到 JSON 請求和響應(yīng),使用 protoc 時,每個 RPC 必須使用 google.api.http 選項定義 HTTP 方法和路徑。

因此,我們需要將 google/api/http.proto 導(dǎo)入添加到 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"
};
}
}
...

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

生成 gRPC-Gateway 存根

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

在使用 protoc 生成存根之前,我們需要將一些依賴項復(fù)制到 proto 文件目錄中。將 googleapis 的子集從官方存儲庫下載并復(fù)制到本地 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 多路復(fù)用器。

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

啟動服務(wù)

grpc 服務(wù)

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

響應(yīng)結(jié)果:

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

04總結(jié)

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

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

Go gRPC 客戶端將 protobuf 結(jié)構(gòu)編碼為 protobuf 二進(jìn)制格式,并將其發(fā)送到 gRPC 服務(wù)器。gRPC 服務(wù)器處理請求并以 protobuf 二進(jìn)制格式返回響應(yīng)。

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

圖片來自 gRPC-Gateway 官方文檔


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

2022-04-29 11:52:02

API代碼HTTP

2021-09-13 05:02:49

GogRPC語言

2021-10-18 05:00:38

語言GoRequestHTTP

2021-09-26 10:20:06

開發(fā)Golang代碼

2021-07-28 11:46:51

工具gRPC客戶端

2021-09-01 23:29:37

Golang語言gRPC

2021-05-07 15:28:03

Kafka客戶端Sarama

2022-01-05 08:03:23

C#通信Rest

2025-01-13 06:00:00

Go語言gRPC

2021-11-29 07:47:57

gRPCGUI客戶端

2025-02-04 13:53:18

NixGogRPC

2023-03-28 07:03:15

gRPCMetadata

2023-03-02 07:20:10

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

2024-04-22 09:30:24

2024-02-05 08:50:57

Golang標(biāo)準(zhǔn)庫客戶端

2025-05-20 09:39:57

GogRPC微服務(wù)

2023-06-10 23:01:41

GrpcProtobuf數(shù)據(jù)

2023-09-06 07:17:57

2009-12-21 10:19:05

Silverlight

2023-03-05 23:11:07

Go語言服務(wù)
點贊
收藏

51CTO技術(shù)棧公眾號