gRPC 基础入门

RPC 的定义这里就不再说,看文章的同学都是成熟的开发。gRPC 是 Google 开源的高性能跨语言的 RPC 方案,该框架的作者 Louis Ryan 阐述了设计这款框架的动机,有兴趣的同学可以看看: gRPC的动机和设计原则 。

另一个值得一提的问题是,众所周知 RPC 框架基本都是直接基于 TCP 协议自研数据结构和编解码方式,但是 gRPC 却完全不是这样,它使用 HTTP/2 协议来传输数据。基于这一点来说, yRPC 肯定就不是性能最佳的那一款 RPC 框架。但是在不追求顶格 QPS 的前提下,通用性和兼容性也是不可忽略的要素。

如果要探究为什么 gRPC 要选择使用 HTTP/2 作为底层协议,这个其实也很好解释。HTTP 协议作为 Web 端标准协议在 Google 内被大规模广泛使用。为了解决 1.x 的问题,Google 将自研的 SPDY 协议公开并推动基于 SPDY 的 HTTP/2 协议。所以 gRPC 从兼容性和推广 HTTP/2 两个角度来说有充足理由选择 HTTP/2,何况基于 HTTP/2 的一些新特性也会让实现方案上少写很多代码。

这里衍生出另一个基础问题:既然底层使用 HTTP/2,那为啥还要用 RPC,不直接用 Restful 的方式更直接吗。RPC 通常使用二进制编码来压缩消息的内容,Restful 更多的使用 JSON 格式,消息体中的冗余数据比较多,性能不如 RPC。

说了这么多题外话下面我们还是看一下作为业内使用率比较高的一款 RPC 框架是如何跑起来的。

开始前的准备

因为 gRPC 使用 Protocol Buffers 做为协议传输编码格式,我们先安装 Protocol Buffers 。具体安装大家可以自行搜索教程,我这里使用 mac 的 brew 来安装。

因为原生的 Protobuf 并不支持将 .proto 文件编译为 Go 源码,后面 Go 官方单独开发了一款编译插件:

Copy
go get -u github.com/golang/protobuf/protoc-gen-go
无论你是通过 go get 的方式安装还是通过别的方式,确保它在 $GOPATH/bin 中以便编译器protoc能够找到它。通过这个插件你可以将 .proto 文件编译为 Go 文件。并且在 protoc-gen-go 插件中还提供了专门的 gRPC 编译相关的支持,可以将 pb 文件中定义的 rpc service 方法渲染成 Go 对象。

这里对于安装过程简单介绍过去,因为它并不是本文介绍的要点,但是对于大家来说肯定不是那么好绕过去的🐶,安装过程出现问题搜索一下即可,已经有人替你们踩过坑!

声明:以下代码都可以在 Github 仓库中找到。

Hello World 入门

我们先定义一个用于本次测试的 pb 格式:

Copy
syntax = “proto3”; // 版本声明,使用Protocol Buffers v3版本
option go_package = “/”;

package models.pb; // 包名

service Calculate {
rpc Sum (stream SumRequest) returns (SumResponse) {}
}

message SumRequest {
int64 num = 1;
}

message SumResponse {
int64 result = 1;
}
执行如下命令生成对应的 pb 文件:

Copy
protoc --go_out=plugins=grpc:. *.proto
执行完成之后就会在当前目录下生成 HelloWorld.pb.go 文件。

接下来开始编写 服务端和客户端相关的代码。首先引入 gRPC 的包:

Copy
go get -u google.golang.org/grpc
服务端代码如下:

Copy
package grpcTest

import (
“fmt”
“net”
“testing”

pb "gorm-demo/models/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"

)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func TestGrpcServer(t *testing.T) {
// 监听本地的8972端口
lis, err := net.Listen(“tcp”, “:8972”)
if err != nil {
fmt.Printf(“failed to listen: %v”, err)
return
}
s := grpc.NewServer() // 创建gRPC服务器
pb.RegisterGreeterServer(s, &server{}) // 在gRPC服务端注册服务

reflection.Register(s) //在给定的gRPC服务器上注册服务器反射服务
// Serve方法在lis上接受传入连接,为每个连接创建一个ServerTransport和server的goroutine。
// 该goroutine读取gRPC请求,然后调用已注册的处理程序来响应它们。
err = s.Serve(lis)
if err != nil {
	fmt.Printf("failed to serve: %v", err)
	return
}

}
接下来是客户端:

Copy
package grpcTest

import (
“fmt”
“testing”

pb "gorm-demo/models/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"

)

func TestGrpcClient(t *testing.T) {
// 连接服务器
conn, err := grpc.Dial(":8972", grpc.WithInsecure())
if err != nil {
fmt.Printf(“faild to connect: %v”, err)
}
defer conn.Close()

c := pb.NewGreeterClient(conn)
// 调用服务端的SayHello
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: "CN"})
if err != nil {
	fmt.Printf("could not greet: %v", err)
}
fmt.Printf("Greeting: %s !\n", r.Message)

}
分别启动服务端和客户端程序可以看到能够正常的收发消息。

更高端的技能

gRPC 主要有 4 种请求和响应模式,分别是简单模式(Simple RPC)、服务端流式(Server-side streaming RPC)、客户端流式(Client-side streaming RPC)、和双向流式(Bidirectional streaming RPC)。

简单模式(Simple RPC):客户端发起请求并等待服务端响应,就是普通的 Ping-Pong 模式。
服务端流式(Server-side streaming RPC):服务端发送数据,客户端接收数据。客户端发送请求到服务器,拿到一个流去读取返回的消息序列。 客户端读取返回的流,直到里面没有任何消息。
客户端流式(Client-side streaming RPC):与服务端数据流模式相反,这次是客户端源源不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应。
双向流式(Bidirectional streaming RPC):双方使用读写流去发送一个消息序列,两个流独立操作,双方可以同时发送和同时接收。
上面演示的代码就是简单模式,客户端发起请求等待服务器回应。下面的三种数据流模式第一眼看上去的时候感觉很难理解,HTTP 协议在我们的认识中就是 Ping-Pong 模式,请求和应答。流式处理是怎么发生的。

建立在 HTTP 基本原理的基础上, gRPC 对请求处理做了一些包装。当一次请求的数据量过大会有两个问题,第一是超时,第二可能超过网络请求最大包长度限制。对于这种情况下的问题要么业务侧做分解将数据拆分成多次请求返回,要么就是通过关键字的方式返回关键字由业务侧根据关键字二次查询详细数据。

流式处理这个概念相当于逆天改命,跳过上面两种基本的上层处理方案,从底层提供一次请求,多次返回的功能。客户端发起一次流式处理请求,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值