16

In my company, we have a system organized with microservices with a dedicated git repository per service. We would like to introduce gRPC and we were wondering how to share protobuf files and build libs for our various languages. Based on some examples we collected, we decided at the end to go for a single repository with all our protobuf inside, it seems the most common way of doing it and it seems easier to maintain and use.

I would like to know if you have some examples on your side ? Do you have some counter examples of companies doing the exact opposite, meaning hosting protobuf in a distributed way ?

antham
  • 408
  • 4
  • 15

2 Answers2

5

We have a distinct repo for protofiles (called schema) and multiple repos for every microservice. Also we never store generated code. Server and client files are generated from scratch by protoc during every build on CI.

Actually this approach works and fits our needs well. But there are two potential pitfalls:

  1. Inconsistency between schema and microservice repositories. Commits to two different git repos are not atomic, so, at the time of schema updates, there is always a little time period when schema is updated, while microservice's repo is not yet.
  2. In case if you use Go, there is a potential problem of moving to Go modules introduced in Go 1.11. We didn't make a comprehensive research on it yet.
Vitaly Isaev
  • 5,392
  • 6
  • 45
  • 64
  • Thanks for your answer – antham Mar 29 '19 at 19:35
  • What do you mean you never store generated code? Do your microservice repos not contain `x.pb.go` files? Could you please explain the pipeline further – kkyr May 10 '19 at 16:23
  • 1
    @kskyriacou yes, our microservice repos do not contain `x.pb.go`. We build these files from `schema` repo during every CI build, according to the desired version of our API. Developers generate these files for the local development as well. This comes from our desire to store all API declarations in single repository called `schema`. We have really big API (dozens of GRPC services with hundreds of methods), so we need to keep it in a single repo to have it consistent. – Vitaly Isaev May 10 '19 at 17:35
  • where do you define API versions & dependencies between microservices? – kkyr May 10 '19 at 19:22
  • 2
    API version is a semver git tag on `schema` repository. Every time we change our API we post new git tag and build artifact (actually RPM package) with `proto` files. Changes may be either backward-compatible or breaking (this is reflect in major on minor releases). Dependencies between microservices? I'm not sure what you mean, basically dependencies are described as imports in `proto` files. – Vitaly Isaev May 10 '19 at 19:48
  • By dependency I mean what version of the API a microservice consumes, hope that's clearer to you. Thank you for all the information so far! – kkyr May 11 '19 at 03:41
  • @kskyriacou currently we can install RPM package with desired version to our CI or developer's machine, and `protoc` will generate appropriate `pb.go` files. But we're looking towards using Go modules, it just not seem to be stable enough, and we also hope that `protobuf`/`grpc-go` community will provide generic tool to generate API based on Go modules. If you're interested, have a look at the concepts of https://github.com/goproxyio/goproxy – Vitaly Isaev May 13 '19 at 08:03
  • howcome you're using RPM packages instead of getting protos from `schema` directly? – kkyr May 13 '19 at 08:55
  • @kskyriacou it makes no difference :) you can either `git clone schema -v %{version}`, or `dnf install schema-%{version}`, the result will be the same. But we prefer `rpm` because RHEL is our target platform, and we ship everything (including build deps) as RPM packages. – Vitaly Isaev May 15 '19 at 08:28
3

Each of our microservices has it's own API (protobuf or several protobuf files). For each API we have separate repository. Also we have CI job which build protoclasses into jar (and not only for Java but for another language too) and publish it into our central repository. Than you just add dependencies to API you need.

For example, we have microservice A, we also have repository a-api (contains only protofiles) which build by job into jar (and to another languages) com.api.a-service.<version>

Optio
  • 7,244
  • 2
  • 22
  • 30