如何维护原始文件?

How to Maintain Proto Files?

我已经创建了 3 个原型文件并希望将其保存在 git 存储库中:

与所有其他文件分开。 存储库仅包含 .proto 个文件。我有 3 个微服务,每个微服务都有自己的存储库,使用这些 proto 文件相互通信:

您可以在上图中看到,proto 文件正在从不同的微服务中消费。

假设,我要更改 Protofile2 并将更改推送到 proto 存储库,请记住原始文件存储库与微服务存储库分开:

当我 运行 go testservice1service2 上时,它应该告诉我,Protofile2 已更改或没有与 service2 文件夹中的 proto 文件相同的哈希:

我必须重新生成代码。

是否有解决问题的工具?或者我该如何解决?

通常人们会尝试使协议缓冲区向后兼容,以便当原型文件更改时,依赖于原型文件的服务不一定需要更改。参见 https://developers.google.com/protocol-buffers/docs/proto3#updating

不过,如果要检查,可以使用proto.GetProperties(msgType)编写测试。将预期的结构属性放在文字中,并使用 reflect.DeepEqual 将其与您通过调用 proto.GetProperties 对原型的动态类型获得的动态结构属性进行比较。像这样:

func TestMyProtoStructVersion(t *testing.T) {
    gotProps := proto.GetProperties(reflect.TypeOf(&mypb.MyProtoStruct{}))
    if !reflect.DeepEqual(gotProps, wantMyProtoStructProps) {
        t.Errorf("MyProtoStruct proto has changed")
    }
}

您可以使用 go generate 来自动创建包含您可以包含在测试中的协议缓冲区的预期结构属性 (wantMyProtoStructProps) 的文件。

这是我的建议:

  • 将您的原型(及其生成的 makefile)存储在单个 git 存储库中。为了简化导入,每个定义都应该在自己的目录中
  • 用版本标记回购 - 特别是在潜在的破坏性变化上
  • 从您的微服务中导入特定的原型定义,例如import "github.com/me/myproto/protodef2"
  • use go modules(在 2019 年与 go v1.11 一起引入)以确保微服务 X 获得兼容版本的 protobuf Y

关于第 2 点——正如@PaulHankin 提到的——尽量不要破坏向后兼容性。可以删除 Protobuf 字段,但只要剩余字段索引不变,旧客户端调用仍将与较新的 proto defs 兼容。