0. 概述

如果你经常使用 GRPC 并且定义 protobuf 的话,那么你一定会遇到很多不爽的问题,比如 pb 格式化,代码生成等,本文将带你一除所有关于 protobuf 的各种烦恼。

其实,我这里想说的是一个 Uber 开源的 Protobuf 工具 prototool,它可以对 protobuf 进行各种我们期望的工作,例如格式化 protobuf,生成测试桩,作为客户端调试等。基于这个工具的功能比较多,我就挑选两个比较常用的功能进行介绍,分别是:

这些都是在平时工作中会经常使用到的功能,所以我觉得比较值得拿出来介绍一下。

1. 安装 prototool

环境不同,安装的方式也不同,如果你使用的是 CentOS,那么可以按照我的步骤来,如果不是,那么你需要参考这里的指导:prototool 安装指导,如果是 windows 用户,那可能需要绕行了。

  1. [root@liqiang.io]# curl -sSL \
  2. https://github.com/uber/prototool/releases/download/v1.8.0/prototool-$(uname -s)-$(uname -m) \
  3. -o /usr/local/bin/prototool && \
  4. chmod +x /usr/local/bin/prototool

安装完毕之后,我习惯性得做个简写,然后顺便测试一下安装是否正常:

  1. [root@liqiang.io]# alias pt=prototool
  2. [root@liqiang.io]# pt version
  3. Version: 1.8.0
  4. Default protoc version: 3.8.0
  5. Go version: go1.12.4
  6. OS/Arch: linux/amd64

一切正常,可以进行下一步的尝试了。

2. 格式化 protobuf

经常写 protobuf,即使有 IDE 的辅助,但是由于修改得比较频繁,所以很容易就导致 proto 的格式乱了,看上去很不舒服,以前都需要自己用 tab 慢慢调,但是现在有了好工具了,那么就可以直接通过工具来格式化啦,下面就先马上上手试用一波:

  1. [root@liqiang.io]# wget https://raw.githubusercontent.com/gogo/grpc-example/master/proto/example.proto
  2. [root@liqiang.io]# pt format bar.proto
  3. ... ...
  4. // Hello is a hello.
  5. message Hello {
  6. int64 hello = 1;
  7. }

因为太简单了,以至于都很难遇到一些错误,但是,就是这么个用法;但是,就是再简单我也要玩出点花来,例如,这里的缩进只有 2 个空格,我不爽,我要 4 个,怎么做?不好意思,实现不了,从某个版本开始,format 的所有配置都被移除了,所以,你必须使用 Uber 的默认格式。

3. prototool 配置文件

但是,如果你有其他自定义需求,那么就可以了解一下 prototool 的配置文件了。可以通过 config init 命令快速得生成一个配置文件:

  1. [root@liqiang.io]# pt config init
  2. [root@liqiang.io]# cat prototool.yaml
  3. protoc:
  4. version: 3.8.0
  5. lint:
  6. group: uber2

我加一条我的自定义需求,ENUM 的值必须都是大写的:

  1. [root@liqiang.io]# cat prototool.yaml
  2. protoc:
  3. version: 3.8.0
  4. lint:
  5. group: uber2
  6. rules:
  7. add:
  8. - ENUM_NAMES_CAPITALIZED

然后来测试一下:

  1. [root@liqiang.io]# cat bar.proto
  2. .. ...
  3. // Size is for shirt selling.
  4. enum Size {
  5. SIZE_INVALID = 0;
  6. SIZE_Small = 1;
  7. SIZE_Medium = 2;
  8. SIZE_LARGE = 3;
  9. }
  10. [root@liqiang.io]# pt lint bar.proto
  11. bar.proto:41:3:Field name "SIZE_Small" must be UPPER_SNAKE_CASE.
  12. bar.proto:42:3:Field name "SIZE_Medium" must be UPPER_SNAKE_CASE.

OK,是我想要的,配置还是有效的,但是,如果你尝试过,你会发现这并不是很爽,因为它有很多规矩都是内置的,比如 ENUM 的默认值必须是 XXX_INVALID,我擦,这能强迫的?

4. 客户端调用

最后一个示例就要来演示一下如何通过 prototool 进行命令行的调用了,第一步还是要跑一个服务器起来,出于方便,我就使用官方的示例了:

  1. [root@liqiang.io]# git clone https://github.com/uber/prototool.git
  2. [root@liqiang.io]# cd prototool
  3. [root@liqiang.io]# make example
  4. [root@liqiang.io]# go run example/cmd/excited/main.go # run in another terminal

然后我再开一个命令行窗口,使用 prototool 进行调用:

  1. [root@liqiang.io]# prototool grpc example \
  2. > --address 0.0.0.0:8080 \
  3. > --method uber.foo.v1.ExcitedAPI/Exclamation \
  4. > --data '{"value":"hello"}'
  5. {"value":"hello!"}
图 1:使用 prototool 调用 GRPC 服务器

可以看到,我输入什么,就输出了什么,正如我所期待的。

5. Ref