Go gRPC Hello World

概述

开始 gRPC 了,这篇文章学习使用 gRPC,输出一个 Hello World。

    用 Go 实现 gRPC 的服务端。

    用 Go 实现 gRPC 的客户端。

gRPC 支持 4 类服务方法,咱们这次实现 单项 RPC 和 服务端流式 RPC。

四类服务方法

单项 RPC

服务端发送一个请求给服务端,从服务端获取一个应答,就像一次普通的函数调用。

rpc SayHello(HelloRequest) returns (HelloResponse){}

服务端流式 RPC

客户端发送一个请求给服务端,可获取一个数据流用来读取一系列消息。客户端从返回的数据流里一直读取直到没有更多消息为止。

rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}

客户端流式 RPC

客户端用提供的一个数据流写入并发送一系列消息给服务端。一旦客户端完成消息写入,就等待服务端读取这些消息并返回应答。

1
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {}

 



双向流式 RPC

两边都可以分别通过一个读写数据流来发送一系列消息。这两个数据流操作是相互独立的,所以客户端和服务端能按其希望的任意顺序读写,例如:服务端可以在写应答前等待所有的客户端消息,或者它可以先读一个消息再写一个消息,或者是读写相结合的其他方式。每个数据流里消息的顺序会被保持。

1
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){}

 



安装

安装 protobuf 编译器

1
brew install protobuf

 



验证:

1
2
protoc --version   
//输出:libprotoc 3.7.1

 



安装 Go protobuf 插件

1
2
go get -u github.com/golang/protobuf/proto   
go get -u github.com/golang/protobuf/protoc-gen-go

 


安装 grpc-go

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

 




写个 Hello World 服务

    编写服务端 .proto 文件

    生成服务端 .pb.go 文件并同步给客户端

    编写服务端提供接口的代码

    编写客户端调用接口的代码

目录结构

    ├─ hello  -- 代码根目录    
    │  ├─ go_client    
    │     ├── main.go    
    │     ├── proto    
    │         ├── hello    
    │            ├── hello.pb.go    
    │  ├─ go_server    
    │     ├── main.go    
    │     ├── controller    
    │         ├── hello_controller    
    │            ├── hello_server.go    
    │     ├── proto    
    │         ├── hello    
    │            ├── hello.pb.go    
    │            ├── hello.proto

这样创建目录是为了 go_client 和 go_server 后期可以拆成两个项目。

编写服务端 hello.proto 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
syntax = "proto3"; // 指定 proto 版本   
package hello;     // 指定包名   
// 定义 Hello 服务   
service Hello {   
    // 定义 SayHello 方法   
    rpc SayHello(HelloRequest) returns (HelloResponse) {}   
    // 定义 LotsOfReplies 方法   
    rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){}   
}   
// HelloRequest 请求结构   
message HelloRequest {   
    string name = 1;   
}   
// HelloResponse 响应结构   
message HelloResponse {   
    string message = 1;   
}

 



了解更多 Protobuf 语法,请查看:

1
https://developers.google.com/protocol-buffers/

 



生成服务端 .pb.go

protoc -I . --go_out=plugins=grpc:. ./hello.proto

同时将生成的 hello.pb.go 复制到客户端一份。

查看更多命令参数,执行 protoc,查看 OPTION 。

编写服务端提供接口的代码

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// hello_server.go   
  package hello_controller   
  import (   
      "fmt"   
      "golang.org/x/net/context"   
      "hello/go_server/proto/hello"   
  )   
  type HelloController struct{}   
  func (h *HelloController) SayHello(ctx context.Context, in *hello.HelloRequest) (*hello.HelloResponse, error) {   
      return &hello.HelloResponse{Message : fmt.Sprintf("%s", in.Name)}, nil   
  }   
  func (h *HelloController) LotsOfReplies(in *hello.HelloRequest, stream hello.Hello_LotsOfRepliesServer)  error {   
      for i := 0; i < 10; i++ {   
          stream.Send(&hello.HelloResponse{Message : fmt.Sprintf("%s %s %d", in.Name, "Reply", i)})   
      }   
      return nil   
  }
 
  // main.go   
  package main   
  import (   
      "log"   
      "net"   
      "hello/go_server/proto/hello"   
      "hello/go_server/controller/hello_controller"   
      "google.golang.org/grpc"   
  )   
  const (   
      Address = "0.0.0.0:9090"   
  )   
  func main() {   
      listen, err := net.Listen("tcp", Address)   
      if err != nil {   
          log.Fatalf("Failed to listen: %v", err)   
      }   
      s := grpc.NewServer()   
      // 服务注册   
      hello.RegisterHelloServer(s, &hello_controller.HelloController{})   
      log.Println("Listen on " + Address)   
      if err := s.Serve(listen); err != nil {   
          log.Fatalf("Failed to serve: %v", err)   
      }   
  }

 



运行:

 

1
2
go run main.go   
  2019/07/28 17:51:20 Listen on 0.0.0.0:9090

 


编写客户端请求接口的代码

  
 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package main   <br>import (   
        "hello/go_client/proto/hello"   
        "io"   
        "log"   
        "golang.org/x/net/context"   
        "google.golang.org/grpc"   
    )   
    const (   
        // gRPC 服务地址   
        Address = "0.0.0.0:9090"   
    )   
    func main() {   
        conn, err := grpc.Dial(Address, grpc.WithInsecure())   
        if err != nil {   
            log.Fatalln(err)   
        }   
        defer conn.Close()   
        // 初始化客户端   
        c := hello.NewHelloClient(conn)   
        // 调用 SayHello 方法   
        res, err := c.SayHello(context.Background(), &hello.HelloRequest{Name: "Hello World"})   
        if err != nil {   
            log.Fatalln(err)   
        }   
        log.Println(res.Message)   
        // 调用 LotsOfReplies 方法   
        stream, err := c.LotsOfReplies(context.Background(),&hello.HelloRequest{Name: "Hello World"})   
        if err != nil {   
            log.Fatalln(err)   
        }   
        for {   
            res, err := stream.Recv()   
            if err == io.EOF {   
                break   
            }   
            if err != nil {   
                log.Printf("stream.Recv: %v", err)   
            }   
            log.Printf("%s", res.Message)   
        }   
    }

 



运行:

1
2
3
4
5
6
7
8
9
10
11
go run main.go   
2019/07/28 17:58:13 Hello World   
2019/07/28 17:58:13 Hello World Reply 0   
2019/07/28 17:58:13 Hello World Reply 1   
2019/07/28 17:58:13 Hello World Reply 2   
2019/07/28 17:58:13 Hello World Reply 3   
2019/07/28 17:58:13 Hello World Reply 4   
2019/07/28 17:58:13 Hello World Reply 5   
2019/07/28 17:58:13 Hello World Reply 6   
2019/07/28 17:58:13 Hello World Reply 7   
2019/07/28 17:58:13 Hello World Reply 8   

 

posted @   it-world  阅读(323)  评论(0编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理
点击右上角即可分享
微信分享提示