Starter template for a monorepo for Go microservices using gRPC, Bazel, and Tilt
If you want to use Nix, all you need to do is
install Nix. Then, just run nix-shell
from
the repository root to get a fully-configured shell.
However, some of your tools (e.g. IDE) might behave better if you also install things locally using the directions below.
If you're using macOS or Linux, you can install all required tools easily using
the Homebrew bundle defined in Brewfile
:
brew bundle install
Even if you're using Windows, you should probably use the Windows Subsystem for Linux wherever possible.
Some of the tools can also be installed on your Windows instance to allow IDE integration. The easiest way to do this is to use Chocolatey:
choco install go bazelisk buildifier protoc
If for any reason you need to install them manually, this table contains all of the required tools:
Run the tidy.sh script to initialize your repository after cloning and installing prerequisites:
bazel run //:tidy
You should also run this script after doing any of the following:
- Modifying protobuf files
- Adding/remove dependencies to Go code
If you haven't already, start up a Kubernetes cluster:
minikube start
Then, run Tilt and follow the instructions in the terminal to open the web console:
tilt up
bazel run //src/example/service:server
bazel run //src/example/web/server
grpc_cli
is an easy way to issue requests to the gRPC server:
grpc_cli call localhost:50051 ExampleService/GetExample "id: 'foo'"
grpc_cli call localhost:50051 ExampleService/SetExample "id: 'foo', data: {text: 'bar'}"
grpc_cli call localhost:50051 ExampleService/GetExample "id: 'foo'"
- Add code quality scan to CI
- Add code coverage to CI
- Add Gazelle to CI
- Add PR comments for CI errors wherever possible
- Add git hooks and repository setup script
- Generify HTTP server
- Add documentation for CI
- Add database to environment
- Add ORM to any example server
- Add service resource dependencies to Tilt environment
- Add project configuration/generator/wizard so people don't get features they don't want
- Add TypeScript React app to example HTTP server
- Add support for other backend languages
- Add Deno scripts to simplify custom workflows
- Add production deployment examples
- Add dynamic configs to environment
- Add pubsub to any example server
- Add cache to any example server
- Add authentication to generic server
- Add authorization to generic server
- Add auditing to generic server
- Add monitoring to generic server
- Add distributed tracing to generic server
- Add single-server integration tests
- Add multi-server API simulation tests
- Add multi-server end-to-end tests
- Add new service setup wizard
The goal of this template is to provide something that you can use to instantly create a production-worthy enterprise microservice environment. The environment aims to be opinionated about:
- Core dependencies (e.g. Bazel, Protocol Buffers)
- Practices
- Abstractions (e.g. good API definitions, service isolation/composition).
However, these pieces should be able to plug into any particular technologies (e.g. PostgreSQL, Okta, Kong) desired, and this template should remain strictly neutral on those opinions. Providing plugins/helpers to make certain integrations easier does not mean assuming that technology will be used.
The assumptions we make about the target environment are:
- It will use Bazel for builds (could support others in the future)
- It will contain services written in Go (could support others in the future)
- It will use Protocol Buffers for service descriptors (could support others in the future)
- It will use gRPC and/or HTTP for transport
- It will run in Kubernetes
- It will use Tilt to manage local development environments
Currently, most of the custom work in this environment is contained within this repo. That means that you won't get any future updates made, but it also means you can customize things to your heart's desire.
The eventual goal is to strike a good balance on this, allowing both models easily. It's quite possible that those shared mechanisms will be removed from this repository and used as shared resources in the future, similarly to how we use existing tools like Gazelle.
There are two fundamentally different things that people might mean when they say these words, so it's important to be clear. When this environment discusses these terms, they have these definitions:
- Service: An API with defined methods that take certain inputs and produce outputs
- Server: A long-running application that provides service(s) over a network interface
These should be decoupled as much as possible. The size of your thread pool (server) may be related to the kind of data processing in your business logic (service), but they are still separate concerns that are often managed by separate people.