gRPC初识相关介绍以及简单模式
一、Grpc是什么
grpc 是 google 开源的一款网络框架,具有极好的性能,可能是目前性能最好的网络框架,支持流式 rpc。 可以很方便地构建消息订阅发布系统,支持几乎所有主流的语言,运行非常稳定。基于HTTP2.0传输数据,数据序列化框架为Google开源的Protocol Buffers
开始之前首先你要知道网络框架为你做了哪些事情:
- 网络协议序列化与反序列化
- 网络底层通信
- 并发管理
以及需要你做哪些事情:
- 定义通信的内容(通过协议文件)
- 实现通信的方法(实现协议接口)
二、ProtoBuf
需要工具主要包括:
- 编译器:protoc,以及一些官方没有带的语言插件
- 运行环境:各种语言的 protobuf 库,不同语言有不同的安装来源
构建基于Golang的Grpc环境
这里我们以golang语言为实例,来使用grpc,安装环境步骤如下:
- 安装protoc
$ git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc $ git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net $ git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text $ git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto $ cd $GOPATH/src/ $ go install google.golang.org/grpc // 安装grpc $ protoc --version // 检查是否安装成功
- go protoc-gen-go插件
$ go get -u github.com/golang/protobuf/{proto,protoc-gen-go} // go protoc-gen-go插件
三、简单Hello服务实例
1. 定义协议文件
首先要定义通信的协议,grpc 使用的是 proto3 序列化协议,这是一个高效的协议,具体细节可以看官网:ProtoBuf文档
syntax = "proto3";
package hello;
message HelloReq {
string msg = 1;
}
message HelloRes {
string msg = 1;
}
service Hello {
rpc echo (HelloReq) returns (HelloRes);
}
其中HelloReq
表示请求结构体,里面有一个参数msg
为String类型,HelloRes
表示相应结构体,和请求结构体类似,
service是用来定义服务接口的,本协议文件定义了一个echo
接口,请求参数为HelloReq
,相应结果为HelloRes
。
执行如下命令会自动生成 hello.pb.go 文件,这个过程其实是把上面这个协议翻译成 golang:
$ protoc --go_out=plugins=grpc:. hello.proto
2. 实现协议接口
package services
import (
"context"
"go/grpc/protos"
"fmt"
)
type HelloService struct {}
func (this *HelloService) Echo(ctx context.Context, req *hello.HelloReq) (*hello.HelloRes, error) {
fmt.Printf("message from client: %s\n", req.GetMsg())
res := &hello.HelloRes{
Msg: "Server already receive your msg:" + req.GetMsg(),
}
return res, nil
}
这个协议接口的定义可以在hello.pb.go
中找到,主要是在里面实现的具体的业务逻辑,我们这边做的比较简单,就是读取客户端
的请求信息,然后返回相响应结果给客户端,告诉它服务端已经收到请求了。可以把他理解为MVC里面的C(控制器)。里面的Echo
就是一个
具体的接口方法。
3. 实现服务端
然后我们创建一个server.go
文件来写我们的服务端代码,把我们刚刚时间的HelloService
类注册到grpc服务里面,这样当我们
启动服务的时候,这个接口服务就可以被客户端访问了,这代码如下:
package main
import (
pb "go/grpc/protos"
"net"
"log"
"google.golang.org/grpc"
"go/grpc/consts"
"fmt"
"go/grpc/services"
)
func main() {
listener, err := net.Listen("tcp", consts.PORT)
if err != nil {
log.Fatalf("Failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterHelloServer(s, &services.HelloService{}) // 注册hello service
fmt.Println("Starting server on port ", consts.PORT)
if err := s.Serve(listener); err != nil {
panic(err)
}
}
代码主要有三步:
- 创建grpc服务
- 注册HelloService服务到grpc中
- 监听服务端口
PORT
,然后启动服务
启动服务命令如下:
$ go run server.go
4. 实现客户端
创建客户端文件client.go
,写请求服务端Echo
接口代码:
package main
import (
"google.golang.org/grpc"
"log"
pb "go/grpc/protos"
"os"
"golang.org/x/net/context"
"go/grpc/consts"
"fmt"
"strings"
)
func main() {
conn, err := grpc.Dial(consts.HOST, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
client := pb.NewHelloClient(conn)
res, err := client.Echo(context.Background(), &pb.HelloReq{
Msg: strings.Join(os.Args[1:], " "),
})
if err != nil {
fmt.Errorf("client echo failed. err: [%v]", err)
return
}
fmt.Printf("Msg from server: %s", res.GetMsg())
}
写完代码后,本地访问我们刚才启动的服务端接口:
$ go run client.go Hello World.
实例中代码URL
实例中代码链接:点我点我