Protobuf 简介-ApiHug101

   🤗 ApiHug × {Postman|Swagger|Api...} = 快↑ 准√ 省↓

  1. GitHub - apihug/apihug.com: All abou the Apihug   
  2. apihug.com: 有爱,有温度,有质量,有信任
  3. ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace

Protobuf 简介-开启高质量API开发之旅

docs/handbook/002_protobuf_basic.md · dearxuecom/apihug.com - Gitee.com

Protobuf

Protobuf即Protocol Buffers,是Google公司开发的一种跨语言和平台的序列化数据结构的方式,是一个灵活的、高效的用于序列化数据的协议。与XML和JSON格式相比,Protobuf更小、更快、更便捷。

Protobuf是跨语言的,并且自带编译器(protoc),只需要用protoc进行编译,就可以编译成Java、Python、C++、C#、Go等多种语言代码,并可以直接使用。

定义了要处理的数据的数据结构之后,就可以利用ProtoBuf的代码生成工具生成相关的代码。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言(proto3支持C++, Java, Python, Go, Ruby, Objective-C, C#)或从各种不同流中对你的结构化数据轻松读写。

工作原理

通过 .proto 文件中定义 protocol buffer message 类型,来指定你想如何对序列化信息进行结构化。

每一个 protocol buffer message 是一个信息的小逻辑记录,包含了一系列的 name-value 对

这是一个最基本的message例子 

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.test.google";

message Model {
    int32 id = 1;
    int32 shopId = 2;
    optional string name = 3;
    optional int32 categoryId = 4;
    optional DecimalValue markPrice = 5;
    optional bool onShelf = 6;
    repeated ModelParameterValue parameter = 7;
}

message DecimalValue {
    uint32 scale = 1;
    uint32 precision = 2;
    bytes value = 3;
}

message ModelParameterValue {
    optional int32 id = 1;
    optional int32 parameterId = 2;
    optional string parameterName = 3;
    optional string parameterValue =4;
    optional int32 modelId = 5;
}
  1. 第一行指明当前使用的是proto3语法, 如果不指定则默认为proto2.
  2. java_multiple_files 指的是是否生成多个java文件, false则只编译ModelOuterClass文件
  3. java_package 指定生成的java文件的所在包
  4. optional 表示该字段为可选字段
  5. repeated 表示该字段可以复用,常用于集合定义 

其他对象

除上面的一些数据结构外, 还有一些复杂的数据结构:

Enum

enum Corpus {
    UNIVERSAL = 0;
    WEB = 1;
    IMAGES = 2;
    LOCAL = 3;
    NEWS = 4;
    PRODUCTS = 5;
    VIDEO = 6;
}

注意 ⚠️ 3.0 后, element_number: 必须从0开始, 0表示类型的默认值, 32-bit integer;

是否会导致你不想用的结果? 看具体业务需求, 当然protoc 会再最后自动加一个: UNRECOGNIZED(-1)

所以几种做法:

  1. 第一个也就是 0 永远用 NA 标志, 也就是不用
  2. 业务逻辑层需要处理 NA + UNRECOGNIZED 两个非预期的数值!

Wrapper

3.0 以后, 不可以设置default值, 这个给处理带来了巨坑, 因为程序逻辑中一般有 空值额外处理逻辑!

于是乎引入了 wrapper 去处理这个错误导致的问题:

import "google/protobuf/wrappers.proto";

message Tester {
    google.protobuf.BoolValue email = 1016;
}

message BoolValue {
  // The bool value.
  bool value = 1;
}
Map

repeated 表示该字段可以复用,常用于集合定义, map 对应我们一般意义上的 Map;

建议里面放,同构的数据, 而不是 Any, 或者下面的 Value :

message Tester {
    map<string, google.protobuf.Value> extensions = 15;
}

⚠️ 根据官方 Maps Features 文档, 在 hope 框架里更建议使用兼容变形的 map 方式来定义 map 类型结构, 在语言实现上也能够兼容:

message MapFieldEntry {
  key_type key = 1;
  value_type value = 2;
}

repeated MapFieldEntry map_field = N;
Any

⚠️ Any & Value ⚠️ 在hope 元信息定义类不被采纳!

当无法明确定义数据类型的时候, 可以使用Any表示:

import "google/protobuf/any.proto";

message ErrorStatus {
  string message = 1;
  repeated google.protobuf.Any details = 2;
}

// `Any` contains an arbitrary serialized protocol buffer message along with a
// URL that describes the type of the serialized message.
//
// Protobuf library provides support to pack/unpack Any values in the form
// of utility functions or additional generated methods of the Any type.
//     {
//       "@type": "type.googleapis.com/google.protobuf.Duration",
//       "value": "1.212s"
//     }

message Any {

  string type_url = 1;

  // Must be a valid serialized protocol buffer of the above specified type.
  bytes value = 2;
}

这个是最不建议的!

Value

Value 貌似比 Any 好点点,

message Tester {
    map<string, google.protobuf.Value> extensions = 9;
}

// `Value` represents a dynamically typed value which can be either
// null, a number, a string, a boolean, a recursive struct value, or a
// list of values. A producer of value is expected to set one of these
// variants. Absence of any variant indicates an error.
//
// The JSON representation for `Value` is JSON value.
message Value {
  // The kind of value.
  oneof kind {
    // Represents a null value.
    NullValue null_value = 1;
    // Represents a double value.
    double number_value = 2;
    // Represents a string value.
    string string_value = 3;
    // Represents a boolean value.
    bool bool_value = 4;
    // Represents a structured value.
    Struct struct_value = 5;
    // Represents a repeated `Value`.
    ListValue list_value = 6;
  }
}

Grpc

GRPC, A high performance, open source universal RPC framework, grpc 提供了整套的RPC 从客户端到服务器端,调用, 序列化、反序列化的方式。

在 hope 体系中我们只使用了他的接口定义功能(IDL), 未使用其作为 RPC 框架核心部分:

借助 protobuf 很好的元信息(option) 扩展功能,实现了 protobuf 上扩展 DSL来描述 The OpenAPI Specification

具体设计细节参考 Protobuf DSL 实现 OAS

参考

  1. protobuf
  2. protobuf Git
  3. protobuf gradle plugin
  4. protobuf intellj plugin
  5. GRPC, A high performance, open source universal RPC framework
  6. GRPC Github
  7. API的设计 - 知乎 - 玩家翁伟​​ 一些思路, 这里设计完看到的,比较接近
  8. 深入浅出:如何正确使用 protobuf
  9. WSDL -WSDL is an XML notation for describing a web service
  10. Thrift IDL
  11. ApiHug101-Bilibili
  12. ApiHug101-Youtube

秒懂 ApiHug -005 加个对象

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值