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";
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这里不展开说明。
大功告成,此时客户端与服务端以及完成全部通讯。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。