一. 环境准备。
- 安装
gprc
。
go get -u google.golang.org/grpc
- 安装
protocol buffers
。
下载地址: https://github.com/protocolbuffers/protobuf/releases
下载解压后放入PATH路径下
二. 实现服务端。
- 新建
account.proto
文件。
syntax = \"proto3\";// 定义包名package account;// 可以定义多个服务,每个服务内可以定义多个接口service Waiter {// 定义接口 (结构体可以复用)// 方法 (请求消息结构体) returns (返回消息结构体) {}//注册rpc Register (RegisterReq) returns (RegisterRes) {}//登录rpc Login (LoginReq) returns (LoginRes) {}}// 定义 Req 消息结构//注册请求参数message RegisterReq {// 类型 字段 = 标识号string username = 1; //账号string password = 2; //密码}//登录请求参数message LoginReq {// 类型 字段 = 标识号string username = 1; //账号string password = 2; //密码}// 定义 Res 消息结构//注册返回参数message RegisterRes {string backJson = 1;}//登录返回参数message LoginRes {string backJson = 1;}
- 生成golang的服务代码
protoc --go_out=plugins=grpc:. ./account.proto
- 实现服务端接口
package accountimport (\"golang.org/x/net/context\")// 业务实现方法的容器type AccountServer struct{}//模拟账号数据库var data = make(map[string]string)//实现注册func (s *AccountServer) Register(ctx context.Context, in *RegisterReq) (*RegisterRes, error) {//账号username := in.Username//密码password := in.Password//模拟数据库查询_,exist := data[username]//判断用户是否存在if exist {return &RegisterRes{BackJson: \"{\\\"status\\\":\\\"0\\\",\\\"msg\\\":\\\"用户名已存在\\\"}\"}, nil}//模拟入库data[username] = password//返回return &RegisterRes{BackJson: \"{\\\"status\\\":\\\"666\\\",\\\"msg\\\":\\\"注册成功\\\"}\"}, nil}//实现登录func (s *AccountServer) Login(ctx context.Context, in *LoginReq) (*LoginRes, error) {//账号username := in.Username//密码password := in.Password//模拟数据库查询dataPwd,exist := data[username]//验证if (!exist || password!=dataPwd) {return &LoginRes{BackJson: \"{\\\"status\\\":\\\"0\\\",\\\"msg\\\":\\\"用户名或者密码错误\\\"}\"}, nil}//返回return &LoginRes{BackJson: \"{\\\"status\\\":\\\"666\\\",\\\"msg\\\":\\\"登录成功\\\",\\\"data\\\":{\\\"token\\\":\\\"123456\\\"}}\"}, nil}
- 服务端的
main
文件
package mainimport (\"log\"\"net\"\"google.golang.org/grpc\"\"beegoApp/grpc/account\"\"google.golang.org/grpc/reflection\")func main() {lis, err := net.Listen(\"tcp\", \":8028\") //监听所有网卡8028端口的TCP连接if err != nil {log.Fatalf(\"监听失败: %v\", err)}s := grpc.NewServer() //创建gRPC服务/**注册接口服务* 以定义proto时的service为单位注册,服务中可以有多个方法* (proto编译时会为每个service生成Register***Server方法)* 包.注册服务方法(gRpc服务实例,包含接口方法的结构体[指针])*/account.RegisterWaiterServer(s, &account.AccountServer{})/**如果有可以注册多个接口服务,结构体要实现对应的接口方法* user.RegisterLoginServer(s, &server{})* minMovie.RegisterFbiServer(s, &server{})*/// 在gRPC服务器上注册反射服务reflection.Register(s)// 将监听交给gRPC服务处理err = s.Serve(lis)if err != nil {log.Fatalf(\"failed to serve: %v\", err)}}
三. 实现客户端。
package adminimport (\"beegoApp/controllers\"\"golang.org/x/net/context\"\"google.golang.org/grpc\"\"beegoApp/common\"\"beegoApp/grpc/account\")type LoginController struct {controllers.BaseController}//注册func (this *LoginController) Register(){// 建立连接到gRPC服务conn, err := grpc.Dial(\"127.0.0.1:8028\", grpc.WithInsecure())if err != nil {this.ErrorJson(666, err.Error())}// 函数结束时关闭连接defer conn.Close()// 创建Waiter服务的客户端t := account.NewWaiterClient(conn)// 模拟请求数据username := \"test123\"password := \"123456\"// 调用gRPC接口tr, err := t.Register(context.Background(), &account.RegisterReq{Username:username,Password:password})if err != nil {this.ErrorJson(666, err.Error())}//json转mapres := common.JSONToMap(tr.BackJson)if (res[\"status\"] == \"666\"){//注册成功this.SuccessJson(res[\"data\"])}else{//注册失败this.ErrorJson(123, res[\"msg\"].(string))}}//登录func (this *LoginController) Login(){// 建立连接到gRPC服务conn, err := grpc.Dial(\"127.0.0.1:8028\", grpc.WithInsecure())if err != nil {this.ErrorJson(666, err.Error())}// 函数结束时关闭连接defer conn.Close()// 创建Waiter服务的客户端t := account.NewWaiterClient(conn)// 模拟请求数据username := \"test123\"password := \"123456\"// 调用gRPC接口tr, err := t.Login(context.Background(), &account.LoginReq{Username:username,Password:password})if err != nil {this.ErrorJson(666, err.Error())}//json转mapres := common.JSONToMap(tr.BackJson)if (res[\"status\"] == \"666\"){//登录成功this.SuccessJson(res[\"data\"])}else{//登录失败this.ErrorJson(123, res[\"msg\"].(string))}}
总结
RPC比起HTTP安全性更高,不必每次通信都要像HTTP一样去三次握手,减少了网络开销,所以,RPC性能消耗低,传输效率高,更适合公司内部的服务调用,缺点就是实现复杂。
参考: 快速开始使用grpc(golang版)