文章同步到 www.crownblog.icu/post/grpc_0…
gRPC是什么
gRPC是一种现代化开源的高性能RPC框架,能够运行于任意环境之中。最初由谷歌进行开发。它使用HTTP/2作为传输协议。
在gRPC里,客户端可以像调用本地方法一样直接调用其他机器上的服务端应用程序的方法,帮助你更容易创建分布式应用程序和服务。与许多RPC系统一样,gRPC是基于定义一个服务,指定一个可以远程调用的带有参数和返回类型的的方法。在服务端程序中实现这个接口并且运行gRPC服务处理客户端调用。在客户端,有一个stub提供和服务端相同的方法。
gRPC技术栈
最底层为TCP或Unix Socket协议,在此之上是HTTP/2协议的实现,然后在HTTP/2协议之上又构建了针对Go语言的gRPC核心库。应用程序通过gRPC插件生产的Stub代码和gRPC核心库通信,也可以直接和gRPC核心库通信。
安装gRPC
安装gRPC
go get -u google.golang.org/grpc
安装Protocol Buffers v3
安装用于生成gRPC服务代码的协议编译器,最简单的方法是从下面的链接:github.com/google/prot…下载适合你平台的预编译好的二进制文件(protoc--.zip)。
下载完之后,执行下面的步骤:
- 解压下载好的文件
- 把protoc二进制文件的路径加到环境变量中
安装protoc的Go插件:
go get -u github.com/golang/protobuf/protoc-gen-go
编译插件protoc-gen-go将会安装到GOPATH/bin,它必须在你的$PATH中以便协议编译器protoc能够找到它。
gRPC入门
gRPC是基于Protocol Buffers。
Protocol Buffers是一种与语言无关,平台无关的可扩展机制,用于序列化结构化数据。使用Protocol Buffers可以一次定义结构化的数据,然后可以使用特殊生成的源代码轻松地在各种数据流中使用各种语言编写和读取结构化数据。
Protobuf3 语法指南 colobu.com/2017/03/16/…
编写proto代码
// 版本号
syntax = "proto3";
// 指定包
package proto;
// 定义请求结构体 使用message
message UserRequest {
string name = 1;
}
// 响应结构体
message UserResponse {
int32 id = 1;
string name = 2;
int32 age = 3;
// repeate修饰的是可变数组 go转切片
repeated string hobby = 4;
}
// service方法
service UserInfoService {
rpc GetUserInfo (UserRequest) returns (UserResponse) {
}
}
执行下面的命令,生成go语言源代码:
protoc --go_out=plugins=grpc:./ ./user.proto
编写server端
package main
import (
"context"
"fmt"
"net"
pb "gRPC/proto"
"google.golang.org/grpc"
)
type UserInfo struct{}
func (u *UserInfo)GetUserInfo(ctx context.Context,in *pb.UserRequest) (resp *pb.UserResponse, err error) {
// 通过用户名查询用户信息
name := in.Name
if name == "crown" {
resp = &pb.UserResponse{
Id: 10001,
Name: name,
Age: 21,
Hobby: []string{"学习","others"},
}
}
return
}
func main() {
// 1. 监听本地的8972端口
lis, err := net.Listen("tcp", ":8972")
if err != nil {
fmt.Printf("failed to listen: %v", err)
return
}
// 2. 创建gRPC服务器
s := grpc.NewServer()
// 3. 在gRPC服务端注册服务
pb.RegisterUserInfoServiceServer(s, new(UserInfo))
// 4. 调用服务
err = s.Serve(lis)
if err != nil {
fmt.Printf("failed to serve: %v", err)
return
}
}
编写client端
package main
import (
"context"
"fmt"
pb "gRPC/proto"
"google.golang.org/grpc"
)
func main() {
// 1. 连接服务器
conn, err := grpc.Dial(":8972", grpc.WithInsecure())
if err != nil {
fmt.Printf("faild to connect: %v", err)
}
defer conn.Close()
// 2. 初始化grpc 客户端
c := pb.NewUserInfoServiceClient(conn)
// 3. 调用服务端的GetUserInfo
r, err := c.GetUserInfo(context.Background(), &pb.UserRequest{Name: "crown"})
if err != nil {
fmt.Printf("could not greet: %v", err)
}
fmt.Printf("Greeting: %s !\n", r.Name)
}