Golang 语言 gRPC 服务怎么同时支持 gRPC 和 HTTP 客户端调用?
Posted Golang语言开发栈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Golang 语言 gRPC 服务怎么同时支持 gRPC 和 HTTP 客户端调用?相关的知识,希望对你有一定的参考价值。
大家好,我是 frank。
欢迎大家点击标题下方 rpc CreateToDoList (ToDoListDetail) returns (CreateToDoListResult)
rpc ReadToDoList (ToDoListPage) returns (ReadToDoListByPage)
...生成 gRPC 服务端存根
使用 protoc 命令工具生成存根
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 映射的更多内容,可以参阅 Google API 文档。
生成 gRPC-Gateway 存根
现在,我们已将 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
│ │ └── 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执行以上 protoc 命令工具,生成一个
*.gw.pb.go
文件。创建 grpc-gateway 目录,并创建 main.go 文件,创建 gRPC-Gateway 多路复用器。
func main()
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
mux := runtime.NewServeMux()
opts := []grpc.DialOptiongrpc.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)
完整代码,请参阅 Github。
启动服务
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 如何实现同时支持 gRPC 和 RESTful 风格的 API。
当 HTTP 请求到达 gRPC-Gateway 时,它会将 JSON 数据解析为 protobuf 消息。然后,它使用解析的 protobuf 消息发出正常的 Go gRPC 客户端请求。
Go gRPC 客户端将 protobuf 结构编码为 protobuf 二进制格式,并将其发送到 gRPC 服务器。gRPC 服务器处理请求并以 protobuf 二进制格式返回响应。
Go gRPC 客户端将其解析为 protobuf 消息,并将其返回到 gRPC-Gateway,后者将 protobuf 消息编码为 JSON 并将其返回到原始客户端。
图片来自 gRPC-Gateway 官方文档
推荐阅读:
Golang 语言怎么打印结构体指针类型字段的值?
Golang 语言 gRPC 使用的接口设计语言 protobuf
Golang 语言 gRPC 到底是什么?
Golang 语言 gRPC 怎么使用?
Golang 语言编写 gRPC 实战项目
参考资料:
https://github.com/grpc-ecosystem/grpc-gateway
https://github.com/googleapis/googleapis
https://github.com/googleapis/googleapis.github.io/
扫描二维码或回复「微信群」,加入微信群
点「赞」和「在看」是最大的支持Golang RPC 之 gRPC
gRPC 简介:
gRPC 是一款高性能、开源的 RPC 框架,产自 Google,基于 ProtoBuf 序列化协议进行开发,支持多种语言(Golang、Python、Java等)。因为 gRPC 对 HTTP/2 协议的支持使其在 Android、IOS 等客户端后端服务的开发领域具有良好的前景。gRPC 提供了一种简单的方法来定义服务,同时客户端可以充分利用 HTTP2 stream 的特性,从而有助于节省带宽、降低 TCP 的连接次数、节省CPU的使用等。
安装:
gRPC 的安装
$ go get -u google.golang.org/grpc
因为 gRPC 是基于 protobuf 实现的接口序列化,所以也要安装 protobuf: 。
实践:
下面我们使用 gRPC 定义一个接口,该接口实现对传入的数据进行大写的格式化处理。
创建项目 golang Demo 工程:
Paste_Image.png
client目录下的 main.go 实现了客户端用于发送数据并打印接收到 server 端处理后的数据
server 目录下的 main.go 实现了服务端用于接收客户端发送的数据,并对数据进行大写处理后返回给客户端
example 包用户编写 proto 文件并生成 data 接口
定义 gRPC 接口:
syntax = "proto3"; package example; service FormatData { rpc DoFormat(Data) returns (Data){} } message Data { string text = 1; }
实现 server 端
package main import ( "Demo/example" "net" "google.golang.org/grpc" "google.golang.org/grpc/reflection" "golang.org/x/net/context" "strings" "log" ) // 定义监听地址 const ( HOST string = "localhost" PORT string = "8080" ) // 定义接口 type FormatData struct{} func (fd *FormatData) DoFormat(ctx context.Context, in *example.Data) (out *example.Data, err error) { str := in.Text out = &example.Data{Text: strings.ToUpper(str)} return out, nil } // 直接在 main 方法中注册接口 func main() { listener, err := net.Listen("tcp", HOST+":"+PORT) if err != nil { log.Fatalln("faile listen at: " + HOST + ":" + PORT) } else { log.Println("Demo server is listening at: " + HOST + ":" + PORT) } rpcServer := grpc.NewServer() example.RegisterFormatDataServer(rpcServer, &FormatData{}) reflection.Register(rpcServer) if err = rpcServer.Serve(listener); err != nil { log.Fatalln("faile serve at: " + HOST + ":" + PORT) } }
实现 client 端:
package main import ( "google.golang.org/grpc" "log" "Demo/example" "golang.org/x/net/context" ) // 定义请求地址 const ( ADDRESS string = "localhost:8080" ) // main 方法实现对 gRPC 接口的请求 func main() { conn, err := grpc.Dial(ADDRESS, grpc.WithInsecure()) if err != nil { log.Fatalln("Can't connect: " + ADDRESS) } defer conn.Close() client := example.NewFormatDataClient(conn) resp,err := client.DoFormat(context.Background(), &example.Data{Text:"hello,world!"}) if err != nil { log.Fatalln("Do Format error:" + err.Error()) } log.Println(resp.Text) }
执行验证结果:
先启动 server,之后再执行 client
client 侧控制台如果打印的结果为: HELLO,WORLD! ,证明 gRPC 接口定义成功
本文来自:
查看原文:
以上是关于Golang 语言 gRPC 服务怎么同时支持 gRPC 和 HTTP 客户端调用?的主要内容,如果未能解决你的问题,请参考以下文章