RPC
RPC(Remote Procedure Call: 近程过程调用)是一个计算机通信协议,该协定容许运行于一台计算机的程序调用另一个地址空间(通常为一个凋谢网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额定地为这个交互作用编程(无需关注细节)。
gRPC(https://grpc.io/about)
gRPC 是一个古代的开源高性能近程过程调用(RPC)框架,能够在任何环境中运行。它能够高效地连贯数据中心中和跨数据中心的服务,并反对可插入的负载平衡、跟踪、健康检查和身份验证。它还实用于分布式计算,以连贯设施、挪动应用程序和浏览器到后端服务。
- 编写.proto 文件,创立 user.proto 文件
syntax = "proto3";
option go_package = "./pb_protobuf/white_board;white_board";
import "google/api/annotations.proto";
package white_board;
message ImCreateBoardRequest {
int64 id = 1;
int32 page_count = 2;
string room_no = 3;
string doc_id = 4;
string url_background = 5;
string page_pos = 6;
string file_url = 7;
string uuid = 8;
string nickname = 9;
}
message ImBoardInfoResponse{
int64 id = 1;
int32 page_count = 2;
string doc_id = 3;
string create_time = 4;
string update_time = 5;
}
message ImGetBoardListByRoomNoResponse{repeated ImBoardInfoResponse BoardList = 1;}
message ImGetBoardByIdRequest{int64 id = 1;}
message ImGetBoardByRoomNoRequest{string room_no = 1;}
message ImBoardResponse{
}
service Board{rpc CreateBoard(ImCreateBoardRequest) returns (ImBoardInfoResponse){}
rpc DeleteBoardById(ImGetBoardByIdRequest) returns (ImBoardResponse){}
rpc DeleteBoardByRoomNo(ImGetBoardByRoomNoRequest) returns (ImBoardResponse){}
rpc GetBoardListByRoomNo(ImGetBoardByRoomNoRequest) returns(ImGetBoardListByRoomNoResponse){}}
syntax = "proto3";
其中第一行指定了咱们应用 protocol buffers 的版本,这里应用 proto3.
option go_package = "path;name";
path:指定生成 buffers 文件的寄存目录,name:给 package 定义别名,能够与 package 不统一。
我的项目目录构造
.
├── README.md
├── app
│ ├── api
│ │ ├── board.go
│ ├── dao
│ │ ├── board.go
│ ├── model
│ │ ├── board.go
│ └── service
│ ├── board.go
├── config
│ ├── config.go
│ ├── config.local.yml
│ ├── config.yml
│ ├── database
│ │ └── database.go
│ └── init.go
├── constant
│ └── constant.go
├── gateway
│ └── gateway.go
├── go.mod
├── go.sum
├── interfaces
│ ├── impls
│ │ ├── api_error.go
│ │ └── rpc.go
│ └── inter.go
├── log
│ └── debug.log
├── main.go
├── middleware
│ ├── auth.go
│ ├── grpc_exception.go
│ ├── recovery.go
│ └── zap_log.go
├── pb_protobuf
│ ├── white_board
│ │ ├── board.pb.go
├── protobuf
│ ├── white_board
│ │ ├── board.proto
├── s.sh
└── util
├── grpc.go
└── util.go
编写 shell 脚本 s.sh
# !bin/sh
proto_files=`find ./protobuf -maxdepth 2 -name "*.proto"`
for proto_file in ${proto_files[*]}
do
echo `protoc --proto_path=../ -I/$GOPATH/pkg/mod/github.com/grpc-ecosystem/grpc-gateway@v1.14.6/third_party/googleapis -I./protobuf --go_out=plugins=grpc:. ${proto_file}`
done
执行 shell 脚本文件./s.sh,在 pb_protobuf 文件下主动生成 white_board 文件夹,以及对应的 board.pb.go 文件。
测试
创立 grpc 服务端,新建 serve.go 文件
package main
import (
"google.golang.org/grpc"
"im-whiteboard/app/api"
"im-whiteboard/pb_protobuf/white_board"
"log"
"net"
)
func main() {
// 创立 Tcp 连贯
listener, err := net.Listen("tcp", ":8028")
if err != nil {log.Fatalf("监听失败: %v", err)
}
// 创立 gRPC 服务
grpcServer := grpc.NewServer()
// Tester 注册服务实现者
// 此函数在 board.pb.go 中,主动生成
white_board.RegisterBoardServer(grpcServer,&api.Board{})
err = grpcServer.Serve(listener)
if err != nil {log.Fatalf("failed to serve: %v", err)
}
}
创立 grpc 客户端 client.go 文件
package main
import (
"context"
im_service "im-whiteboard/pb_protobuf/white_board"
"log"
"google.golang.org/grpc"
)
// 定义申请地址
const (
//ADDRESS string = constant.WhiteBoardMedia
ADDRESS string = "127.0.0.1:8028"
)
// main 办法实现对 gRPC 接口的申请
func main() {conn, err := grpc.Dial(ADDRESS, grpc.WithInsecure())
if err != nil {log.Fatalln("Can't connect: " + ADDRESS)
}
defer conn.Close()
client := im_service.NewBoardClient(conn)
res, err := client.GetBoardListByRoomNo(context.Background(),&im_service.ImGetBoardByRoomNoRequest{RoomNo: "c0c6487ab418dabab0ccc9f32c36531b",})
if err != nil {log.Fatalln("Do Format error:" + err.Error())
}else{log.Println("res",res)
}
}
而后别离启动 server 和 client 端,我的项目波及 mysql,redis,mongodb 这里不开展阐明。
功败垂成,此时客户端与服务端以及实现全副通信。