Loading

微服务protobuf

image-20241225105554450

protobuf

gRPC是一款语言中立、平台中立、开源的远程过程调用系统,gRPC客户端和服务端可以在多种环境中运行和交互,例如用java写一个服务端,可以用go语言写客户端调用

数据在进行网络传输的时候,需要进行序列化,序列化协议有很多种,比如xml, json,protobuf等

gRPC默认使用protocol buffers,google开源的一套成熟的结构数据序列化机制。

  • 序列化:将数据结构或对象转换成二进制串的过程。

  • 反序列化:将在序列化过程中所产生的二进制串转换成数据结构或对象的过程

protobuf是谷歌开源的一种数据格式,适合高性能,对响应速度有要求的数据传输场景。因为profobuf是二进制数据格式,需要编码和解码。数据本身不具有可读性。因此只能反序列化之后得到真正可读的数据。

  1. 序列化后体积相比Json和XML很小,适合网络传输
  2. 支持跨平台多语言
  3. 消息格式升级和兼容性还不错
  4. 序列化反序列化速度很快
安装
  1. 安装protobuf编译器

    brew install protobuf
    
  2. 安装go专用的proto生成器

    # 安装后会在gopath目录下生成可执行文件,执行protoc命令会自动调用这个插件
    go install  github.com/golang/protobuf/protoc-gen-go@latest
    

    编译器插件proptoc-gen-go可以识别proto文件

基本使用
  • protobuf定义了一种源文件,扩展名是.proto,使用这种源文件可以定义存贮类的内容(消息类型)
  • protobuf有自己的编译protoc,可以将.proto编译成对应的语言文件,然后进行使用
  1. .proto文件

    // 指定proto的语法版本,有2和3版本
    // 结尾必须要;
    syntax = "proto3";
    
    // 表示生成的go文件的存放地址,会自动生成目录
    // 语法一:option go_package = "path;name"; path是目录,name表示生成的go文件所属的包名
    // 语法二: 只写path
    // 生成的go文件的存放地址,会自动生成目录
    option go_package = "./service";
    
    // 文件生成出来的package
    package service;
    
    
    // 消息:传输的对象
    message User{
      // 每个字段后面的数字是其唯一的标识符,不是value,是一个正整数,并且在同一个消息类型中不能重复
      string user = 1;
      int32 age = 2;
    }
    
  2. 命令行执行

    # --go_out=./表示文件要生成的目录,如果文件里配置了go_package,优先级比命令行高
    # 输出到./ 目录下  根据test.proto文件
    protoc --go_out=./  test.proto     
    
  3. 生成 test.pb.go源文件,该文件不要进行修改,但是依赖的包需要下载

  4. 序列化和反序列号-在main.go中

    package main
    
    import (
    	"fmt"
    	"goRpc/service"
    	"google.golang.org/protobuf/proto"
    )
    
    func main() {
    
    	user := &service.User{
    		User: "lll",
    		Age:  20,
    	}
    
    	// 序列化:将go代码序列化为二进制串
    	marshal, err := proto.Marshal(user)
    	if err != nil {
    		panic(err)
    	}
    
    	// 反序列化:将二进制串反序列化为go代码
    	newUser := &service.User{}
    
    	err = proto.Unmarshal(marshal, newUser)
    	if err != nil {
    		panic(err)
    	}
    
    	fmt.Println(newUser.String())
    
    }
    
    
proto文件介绍
  1. message

    message:protobuf中定义的消息关键字,消息就是徐涛传输的数据格式的定义,类似于go中的struct

    数据分别对应于每一个字段,每个字段都有一个名字和类型,字段规则如下:

    • required:消息体中必填字段,不设置会导致编解码异常
    • optional: 消息体中可选字段
    • repeated: 消息体中可重复字段,重复的值的顺序会被保留,在go中重复的会被定义为切片
    • 标识号:在消息体的定义中,每个字段都必须要有一个唯一的标识号,标识号是[0,2^29-1]范围内的一个整数
    message User{
      // 不声明默认是required规则
      string user = 1;  // 标识号1,并不是具体的value
      int32 age = 2; // 标识号2 
      // 可选字段
      optional string  tips = 3;
      // 可重复字段
      repeated string ext = 4;
    }
    
  2. 类型映射

    image-20241225141931449

  3. 默认值

    protobuf2 中使用default来设置字段默认值,protobuf3为各类型定义的默认值

    image-20241225142030467

消息嵌套
  1. 一个proto文件中可以定义多个消息类型,并不只是一个

    message User{
       string user = 1;
      int32 age = 2;
    }
    
    message Category{
      string id = 1;
      string info = 2;
    }
    
  2. 可以在其他消息类型中定义、使用消息类型

    // 消息:传输的对象
    message User{
      string user = 1;
      int32 age = 2;
      // 嵌套
      message Category{
        string id = 1;
        repeated string info = 2;
      }
    }
    
    
    
    message Test{
      // 在消息的父消息类型的外部重用这个消息类型
      User.Category id = 1;
    }
    
    
定义服务

如果想要将消息类型用在RPC系统中,可以在.proto文件中定义一个RPC服务接口,protocol buffer 编译器将会根据所选择的不同语言生成服务接口代码及存根

// 定义了一个RPC服务,Search方法,该方法接收SearchRequest返回SearchResponse
service SearchService {
	//rpc 自定义的方法名字 (要传入的参数结构)返回(要返回的参数结构),参数使用message定义
	rpc Search (SearchRequest) returns (SearchResponse);
}
posted @ 2024-12-25 14:49  木子七  阅读(46)  评论(0)    收藏  举报