这是我参与「第四届青训营 」笔记创作活动的的第3天
Protobuf 实现RPC调用
一、ProtoBuf
protobuf是类似于Json的一种用于数据序列化和反序列化的程序,下面介绍Protobuf的使用步骤。
- 定义
proto文件, 文件的内容就是存储或者是发送的数据结构或者是传输协议- 使用
protobuf编译器便🧬编译自定义的.proto文件,生成.pb.{cc, h}- 使用
protobuf的API进行消息的读写
定义proto文件
- 为需要序列化的数据结构添加消息
message- 为消息中每一个字段指定:
name,type,tag
编译文件
生成
xxx.pb.{h, cc}两个文件,其中内涵了比如说 设定变量的值,进行序列化,反序列化的api
使用API进行序列化 & 反序列化
在新的文件中包含生成的头文件进行调用
二、RPC
什么是RPC
RPC是远程过程调用 (Remote Proceduce Call) ,目标主要是让分布式计算更加容易。RPC框架提供了一种透明的机制让使用者 不用区分本地调用和远程调用。
数据远端调用过程
这里假设用
Json进行序列化操作,假设client端调用了服务端的函数,其实就是向服务端发送了函数f(x)的数据(包括传入的参数,获得的返回值类型等),然后经过序列化之后经过网络发送到对端。对端反序列化获得结构化的数据,进行函数调用,然后以相同的方式发送回client端
如何做到序列化呢?
使用google的
protobuf,前面有描述
使用gRPC框架
适用场景:
- 分布式场景,低延迟高吞吐量
- 点对点实时通信
- 网络受限的环境,适用protobuf进行序列化消息
单项RPC使用(远程的函数调用)
proto文件
syntax = "proto3";
package Helloworld;
//rpc 接口
service Greetes {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloReply {
string name = 1;
string message = 2;
}
message HelloRequest {
string name = 1;
string message = 2;
}
我们的服务名就是
Greetes, 其中SayHello就是实现的函数,参数返回值就是下面定义的结构
server
package main
import (
"context"
"fmt"
"net"
)
type Server struct {
}
//proto生成pb文件,
func (s *Server) SayHello(con context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Name: "呱呱", Message: "早上好"}, nil
}
func main() {
lis, err := net.Listen("tcp", ":9981")
if err != nil {
fmt.Println(err)
return
}
//定义一个rpc的server
server := grpc.NewServer()
//注册服务,相当与注册SayHello接口
pb.RegisterGreetsServer(server, &Server{})
//进行映射绑定
reflection.Register(server)
//启动服务
err = server.Serve(lis)
if err != nil {
fmt.Println(err)
return
}
}
Client
1func main() {
2 //创建一个grpc连接
3 conn, err := grpc.Dial("localhost:8002", grpc.WithInsecure())
4 if err != nil {
5 fmt.Println(err)
6 return
7 }
8 defer conn.Close()
9
10 //创建RPC客户端
11 client := pb.NewGreetsClient(conn)
12 //设置超时时间
13 _, cancel := context.WithTimeout(context.Background(), time.Second)
14 defer cancel()
15
16 // 调用方法
17 reply, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "小冰", Message: "你好吗"})
18 if err != nil {
19 log.Fatalf("couldn not greet: %v", err)
20 }
21 log.Println(reply.Name, reply.Message)
22}
Client端调用方法SayHello就是进行了远程的调用Server的函数