GRPC简介
GRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
在 GRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。
与许多 RPC 系统类似,gRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。
在服务端实现这个接口,并运行一个 gRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
GRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强
Mac安装GRPC
- 先安装 grpc 依赖工具:autoconf,automake, libtool:
brew install autoconf automake libtool
#安装 grpc、protobuf
brew tap grpc/grpc
brew install --with-plugins grpc
安装成功后查看
protoc --version
显示版本
libprotoc 3.7.1
安装protoc-gen-go
将proto文件编译成go代码时,需要protoc-gen-go插件
go get 命令可以借助代码管理工具通过远程拉取或更新代码包及其依赖包,并自动完成编译和安装.
// gRPC运行时接口编解码支持库
go get -u github.com/golang/protobuf/proto
// 从 Proto文件(gRPC接口描述文件) 生成 go文件 的编译器插件
go get -u github.com/golang/protobuf/protoc-gen-go
此时查看GOBIN目录,可以看到protoc-gen-go执行文件
我试过多次,无法自动编译。只能手动编译。
手动编译后,copy文件到GOBIN下,或者其他bin文件下
go get github.com/golang/protobuf/protoc-gen-go
cd $GOPATH/src/github.com/golang/protobuf/protoc-gen-go
go install
copy protoc-gen-go $GOBIN/
# 或者放在 /usr/local/bin/下。在$GOBIN下,始终无法生效
代码实例
Proto文件
syntax = "proto3";
// 命令:protoc --go_out=plugins=grpc:. helloworld.proto
//option java_package = "io.grpc.examples";
package helloworld;
option go_package = "./pb";
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// 消息体 一个package中,不允许定义同名的消息体
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// 定义服务
// The response message containing the greetings
message HelloReply {
string message = 1;
}
执行命令生成GRPC代码
protoc --go_out=plugins=grpc:. helloworld.proto
服务端代码
package main
import (
"net"
"helloworld/pb"
"fmt"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
port = ":50051"
)
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 main() {
//1.初始化一个grpc 对象
s := grpc.NewServer()
//2. 注册服务
pb.RegisterGreeterServer(s, &server{})
//3. 设置监听 指定 ip 端口
lis, err := net.Listen("tcp", port)
if err != nil {
fmt.Printf("failed to listen: %v", err)
return
}
defer lis.Close()
//4. 启动服务
s.Serve(lis)
}
客户端代码
package main
//client.go
import (
"log"
"os"
"helloworld/pb"
"fmt"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// 1. 连接grpc 服务
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
fmt.Printf("did not connect: %v", err)
return
}
defer conn.Close()
//2. 初始化一个grpc 对象
c := pb.NewGreeterClient(conn)
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
// 3.调用远程服务
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
if err != nil {
fmt.Printf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
运行实例
go run server.go
go run client.go