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
│   ├── 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

执行以上 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的使用等。

安装:

  1. gRPC 的安装

    $ go get -u google.golang.org/grpc

  2. 因为 gRPC 是基于 protobuf 实现的接口序列化,所以也要安装 protobuf: 。

实践:

下面我们使用 gRPC 定义一个接口,该接口实现对传入的数据进行大写的格式化处理。

  1. 创建项目 golang Demo 工程:


    Paste_Image.png

    1. client目录下的 main.go 实现了客户端用于发送数据并打印接收到 server 端处理后的数据

    2. server 目录下的 main.go 实现了服务端用于接收客户端发送的数据,并对数据进行大写处理后返回给客户端

    3. example 包用户编写 proto 文件并生成 data 接口

  2. 定义 gRPC 接口:

    syntax = "proto3";
    package example;
    service FormatData {
     rpc DoFormat(Data) returns (Data){}
    }
    message Data {
     string text = 1;
    }
  3. 实现 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)
     }
    }
  4. 实现 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)
    }
  5. 执行验证结果:

    1. 先启动 server,之后再执行 client

    2. client 侧控制台如果打印的结果为: HELLO,WORLD! ,证明 gRPC 接口定义成功

本文来自:

查看原文:


以上是关于Golang 语言 gRPC 服务怎么同时支持 gRPC 和 HTTP 客户端调用?的主要内容,如果未能解决你的问题,请参考以下文章

Golang之gRPC初识

gRPC

golang grpc-源码-网络模型

Go语言入门篇-gRPC基于golang & java简单实现

GoLang -- gRPC框架四大服务

gRPC golang开发简介