前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Golang笔记 6.3 RPC 编程之 gRPC

Golang笔记 6.3 RPC 编程之 gRPC

作者头像
twowinter
发布2020-04-17 11:32:30
1.5K0
发布2020-04-17 11:32:30
举报
文章被收录于专栏:twowinter

前言

我正在学习酷酷的 Golang,可点此查看帖子Golang学习笔记汇总

1 它是什么

gRPC 是一个高性能、开源、通用的 RPC 框架。

A high performance, open-source universal RPC framework.

2 为什么是它!

gRPC is a modern open source high performance RPC framework that can run in any environment. It can efficiently connect services in and across data centers with pluggable support for load balancing, tracing, health checking and authentication. It is also applicable in last mile of distributed computing to connect devices, mobile applications and browsers to backend services.

  • 可运行在任何环境的RPC框架
  • 可以插件式的增加 load balancing, tracing, health checking and authentication 这些支持
  • 也适用于分布式计算的最后一英里

3 详细介绍

先了解几个基本概念,https://grpc.io/docs/guides/concepts/

服务的定义

gRPC 默认使用 protocol buffers 作为接口描述语言,用它来描述服务端接口及消息格式。

代码语言:javascript
复制
service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

gRPC 允许你定义四类服务方法:

  • 单次 RPC,即客户端发送一个请求给服务端,从服务端获取一个应答,就像一次普通的函数调用; rpc SayHello(HelloRequest) returns (HelloResponse){ }
  • 服务端流式 RPC,即客户端发送一个请求给服务端,可获取一个数据流用来读取一系列消息。客户端从返回的数据流里一直读取直到没有更多消息为止; rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){ }
  • 客户端流式 RPC,即客户端用提供的一个数据流写入并发送一系列消息给服务端。一旦客户端完成消息写入,就等待服务端读取这些消息并返回应答; rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) { }
  • 双向流式 RPC,即两边都可以分别通过一个读写数据流来发送一系列消息。这两个数据流操作是相互独立的,所以客户端和服务端能按其希望的任意顺序读写,例如:服务端可以在写应答前等待所有的客户端消息,或者它可以先读一个消息再写一个消息,或者是读写相结合的其他方式。每个数据流里消息的顺序会被保持; rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){ }

使用 API surface

gRPC提供了 protocol buffer 编译器插件,可生成客户端和服务器端代码。 gRPC用户通常在客户端(stub)调用这些API,并在服务器端实现相应的API。

同步与异步

阻塞的同步RPC调用直到服务器收到响应为止是最接近RPC所追求的过程调用抽象的近似方法。 另一方面,网络本质上是异步的,并且在许多情况下能够启动RPC而不阻塞当前线程很有用。

gRPC编程都有同步和异步两种形式。

RPC 生命周期

4 golang 中怎么用

参考 https://grpc.io/docs/quickstart/go/

4.1 安装

安装 gRPC

代码语言:javascript
复制
$ go get -u google.golang.org/grpc

安装 PROTOC 编译器

3.7.1 版本安装示例:

代码语言:javascript
复制
$ PROTOC_ZIP=protoc-3.7.1-linux-x86_64.zip
$ curl -OL https://github.com/google/protobuf/releases/download/v3.7.1/$PROTOC_ZIP
$ sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
$ rm -f $PROTOC_ZIP

3.10.1 版本安装示例:

代码语言:javascript
复制
PROTOC_ZIP=protoc-3.10.1-linux-x86_64.zip
curl -OL https://github.com/protocolbuffers/protobuf/releases/download/v3.10.1/$PROTOC_ZIP
sudo unzip -o $PROTOC_ZIP -d /usr/local bin/protoc
rm -f $PROTOC_ZIP

安装 protoc 的 go 插件

代码语言:javascript
复制
$ go get -u github.com/golang/protobuf/protoc-gen-go

protoc-gen-go 将会安装在 GOBIN, 默认是 GOPATH/bin. 需要在

代码语言:javascript
复制
$ export PATH=$PATH:$GOPATH/bin

4.2 示例 - helloworld

运行
代码语言:javascript
复制
$ cd $GOPATH/src/google.golang.org/grpc/examples/helloworld

开两个终端,分别执行 server 和 client:

代码语言:javascript
复制
$ go run greeter_server/main.go
代码语言:javascript
复制
$ go run greeter_client/main.go

这样执行之后,终端上就有日志打印出来了:

代码语言:javascript
复制
# go run greeter_client/main.go
2019/11/04 12:21:47 Greeting: Hello world
代码语言:javascript
复制
# go run greeter_server/main.go
2019/11/04 12:21:47 Received: world
proto 文件分析
代码语言:javascript
复制
// 1 定义服务
service Greeter {
  // 2 定义服务中的方法
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 3 定义方法中的请求消息格式
message HelloRequest {
  string name = 1;
}

// 4 定义方法中的回复消息格式
message HelloReply {
  string message = 1;
}
client 源码操作分析
代码语言:javascript
复制
  // Step1. grpc 连接
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
  defer conn.Close()

  // Step2. 新建客户端    c := pb.New(ServiceName)Client(conn)
  c := pb.NewGreeterClient(conn)

	// Step3. 准备 context 用于 grpc 请求
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
  defer cancel()
  
  // Step4. 客户端调用预先定义的方法,并传入方法对应的请求  c.(MethodName)(ctx, &pb.(RequestMessageName))
	r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
server 源码操作分析
代码语言:javascript
复制
  // Step1. 配置监听的协议和端口
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
  }
  
  // Step2. 新建 grpc 服务端
  s := grpc.NewServer()
  
  // Step3. 将 pb消息处理 的实例进行注册
  pb.RegisterGreeterServer(s, &server{})
  
  // Step4. 启动监听服务
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
  }

除了这4步常规操作之外,更重要的是定义 pb消息处理 的实例:

代码语言:javascript
复制
// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.Name)
	return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

4.3 示例修改 - 增加一个新的方法

在 pb 中增加新的方法

代码语言:javascript
复制
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // Sends another greeting
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

使用 protoc 自动更新代码

代码语言:javascript
复制
protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld

在 greeter_server/main.go 中更新 server 代码

代码语言:javascript
复制
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
        return &pb.HelloReply{Message: "Hello again " + in.GetName()}, nil
}

在 greeter_client/main.go 中更新 client 代码

代码语言:javascript
复制
r, err = c.SayHelloAgain(ctx, &pb.HelloRequest{Name: name})
if err != nil {
        log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.GetMessage())

运行结果

代码语言:javascript
复制
$ go run greeter_client/main.go
Greeting: Hello world
Greeting: Hello again world

5 小结

  1. 在 .proto 文件中定义服务
  2. 使用 protocol buffer 编译器产生 服务端和客户端 代码
  3. 使用 Go gRPC API 为你的服务编写客户端和服务端

本篇笔记演示了如何使用 gRPC 框架,包括 proto 文件定义服务,使用 pb 编译器产生代码,最后使用 gRPC API 编写 client 和 server 代码。

END

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1 它是什么
  • 2 为什么是它!
  • 3 详细介绍
    • 服务的定义
      • 使用 API surface
        • 同步与异步
          • RPC 生命周期
          • 4 golang 中怎么用
            • 4.1 安装
              • 4.2 示例 - helloworld
                • 运行
                • proto 文件分析
                • client 源码操作分析
                • server 源码操作分析
              • 4.3 示例修改 - 增加一个新的方法
              • 5 小结
              • END
              相关产品与服务
              云服务器
              云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档