vlambda博客
学习文章列表

gRPC开发中写Proto 的注意事项

  • proto文件的注意事项

  • 三种数据通道



一、proto注意事项

1.官方的示例

syntax = "proto3";
option go_package = "google.golang.org/grpc/examples/helloworld/helloworld";option java_multiple_files = true;option java_package = "io.grpc.examples.helloworld";option java_outer_classname = "HelloWorldProto";
package helloworld;
// 定义一个服务service Greeter { // 服务中的一个调用 rpc SayHello (HelloRequest) returns (HelloReply) {}}
// 请求参数message HelloRequest { string name = 1;}
// 响应参数message HelloReply { string message = 1;}
  • 通过 go_package 或 java_package定义编译后的包路径

  • 请求参数命名以 xxxRequest

  • 响应参数命名以 xxxReply

  • 通过 java_multiple_files 声明每个message和service要单独编译成一个文件

2.标识号的分配

字段标识号是指 stringname=1 这句后面的1.

标识号不要求连续,如:

string name = 1;string nickname = 12;string age = 2;

而且可以使用 reserved 指令来保留字段和字段名,如:

reserved 1,2;reserved "name","age";

标识号定义好后,一旦上线不可修改。否则可能会出现字段混乱的情况。

此外,1-15的标识号编码后占一个字节,16~2047 编码后占两个字节,一般不会再多了。

3.uint的使用

因为java中没有无符号整数,所以编译后会变成 long 和 int,那么无符号的限定就没什么作用了。

需要在业务中做校验。

4.枚举类型

proto 中 枚举类型内首个枚举项要求从0开始,考虑到 go 语言中零值是默认值,因此第一个元素一般是保留元素,不标识业务意义。

每个枚举类型内的枚举项也要求是唯一的。比如下面的会导致冲突,编译无法通过:

enum OpType{ None = 0;}enum BizType{ None = 0;}

枚举项内的元素一般不允许重复,除非声明了 allow_alias。比如:

enum Status { option allow_alias = true; None = 0; Doing = 1; Done = 1;}

二、三种数据通道

RPC调用的过程中,一般有三种数据:

  • 主要传输的消息体,message中定义的消息

  • 错误的返回值

  • 公共的参数

本篇只做简单介绍,因为每个点拿出来都足够写一篇文章了,后续会有详细介绍。

1. metadata

gRPC 是基于 http2的,在请求和返回时可以把一些数据放到 header中。

利用这种特性,gRPC构造了一种 key:value结构的数据格式,叫 metadata。

它将header作为载体,可以在请求和响应中额外传输数据。

比如我们定义了metadata 的 appname,在gRPC请求时,会转为如下header:

2.错误返回值

gRPC官方只支持固定几种错误码,这些错误码太少了,无法完全表达具体业务错误。

然而grpc错误中的message也绝不是放置错误标识的字段,因为其不可控性太强。

还有些开发者在定义返回值时,会在定义的时候固定将错误码和消息包含在内,如:

message LoginReply{ int32 code = 1; string msg = 2; int64 uid = 3;}

这也并不是推荐的做法:因为会导致重复工作太多。

Google推荐了一种,把错误详细信息编码后,放到 metadata 来返回的方式。

3.公共参数处理

很多接口也有公共参数,将公共参数放入message中不仅会带来大量重复工作,而且非常不利于后续通用字段的添加。

所以做法还是放到 metadata中。

4.小结

http请求其实就那么几个可以传输的地方:

  • URL中的query参数

  • header

  • POST请求中的body

gRPC将message放到了body,metdata放到了header。