10

我正在使用微服务架构创建一个系统。有两个微服务AB,每个都存在于自己的存储库中。

有一个user.proto包含 protobuf 定义和 gRPC 方法签名的文件。A使用生成user.pb.go作为服务器。B用作user.pb.go客户(的A)。

构造它的一种方法是在 中出现 proto 定义A,并B具有对以下的代码依赖A

 A
 ├── pb
 │   ├── user.proto
 │   └── user.pb.go
 └── service.go
 B
 └── service.go

B-->A

另一种方法是拥有另一个P包含 proto 定义的 repo,AB取决于新的 repo:

 A
 └── service.go
 B
 └── service.go
 P
 ├── user.proto
 └── user.pb.go

A-->P
B-->P

或者新的 repo 可能只包含 proto 文件,并在 A 和 B 中生成代码:

 A
 ├── service.go
 └── pb
     └── user.pb.go
 B
 ├── service.go
 └── pb
     └── user.pb.go
 P
 └── user.proto

这里有什么更好的方法?

4

3 回答 3

1

如果你的团队不喜欢 monorepo,我认为第三种选择是最合适的。1 个用于 proto 文件的 repo。然后,它可以作为 git 子模块包含在 A 和 B 中(如果您使用的是 git)。A 和 B 可以有自己的 protoc 脚本,生成的 protobuf 文件取决于他们使用的编程语言。

于 2019-05-14T03:50:04.247 回答
0

第二种方式更好。

为什么?因为当您添加服务 C 时,它会自然地与 A 和 B 内联。任何现有组件都不需要更改导入路径代码。

是的,第三种方式可以声明这一点,但它会user.pb.go在每个微服务中复制生成的内容。最好合并以避免重复。

您还可以在您的 repo 的顶层(即 A 和 B 级别)使用 go 的内部包功能。重命名Pinternal确保此子包可由A, B(或C等)使用,但不会邀请其他第三方包引用此“内部”包。

于 2019-05-10T18:37:17.910 回答
0

我认为正确的答案取决于你项目的规模。

对于可能在您的团队之外使用的小型项目或项目(例如,开源或什至随 SDK 一起提供给其他团队的专有产品),我更喜欢第一种方法。如果您不在pb.go主存储库中提供生成的代码(文件),您的用户将不会高兴,因为protoc它远不是一个用户友好的工具。

作为第一个选项的变体,我回想起具有所有微服务(所谓的“monorepo”)的单个存储库的项目。他们将生成的pb.go文件直接放入vendor存储库。

对于具有丰富微服务后端的大型 Web 服务,第二个将是更好的选择。您将获得一个完整定义 API 的存储库。这将提高 API 的一致性并帮助您设置发布周期。您可能会或可能不会将文件放在pb.go一起proto,这取决于您的需求,但我们通常不会

于 2019-05-10T22:30:37.163 回答