[TOC]

为什么要了解Bazel

这段时间搞到了bilibili的一部分源码,那个事件你知道的,就不说了。怀着对大牛的向往,打算研究一下,之前听说主程做的这个架构很牛逼,就算是代码泄露也不会对服务器造成影响,而且模块化做的非常好,小弟们码好代码,主程一键做个合并打包发布就行。自动化做的很好。就想知道到底是怎么做的,于是我了解到了他——Bazel。

原文链接 https://filipnikolovski.com/managing-go-monorepo-with-bazel/

使用Bazel管理Go monorepo

InPlayer中,我们有一个使用_微服务_架构风格构建的平台,它基本上将应用程序构建为许多不同服务的集合。在这篇文章中,我将讨论如何建构(structure),构建(build)和部署(deploy)Go应用程序。

我们编写的每一段Go代码都驻留在一个Git存储库中 – 一个monorepo。由于每个库和服务都在一个项目中,因此它允许我们进行交叉更改,而无需使用某些外部包管理工具。基本上,代码不可能不同步,我们所做的每个更改都可以视为一个单元。

虽然好处很明显,但使用Go monorepo的挑战是如何有效地构建和测试每个包。答案 – Bazel

Bazel是什么?

Bazel是一款速度极快的构建工具。它只重建必要的东西,它利用高级缓存机制和并行执行,使您的构建非常,非常快。除了这些功能外,它还可以管理您的代码依赖项,调用外部工具和插件,还可以从二进制可执行文件构建Docker镜像。它使用go build引擎盖,但它也可以支持许多不同的语言,而不仅仅是Go。您可以将它用于Java,C ++,Android,iOS和各种其他语言平台。您可以在三个主要操作系统上运行Bazel – Windows,macOS和Linux。

项目结构

在我们深入了解Bazel之前,首先让我们讨论一下我们的项目结构:

platform目录是我们的根本,一切从这里开始。在该文件夹中,我们有CI配置和src保存所有代码的目录。每个服务都是src文件夹中的子目录,在每个服务中我们都有两个顶级目录,即cmdpkg文件夹。在下面cmd我们有我们的二进制文件(我们的主程序)的pkg目录,该目录用于我们的服务库。

Bazel从名为_workspace_的目录中组织的代码构建软件,该目录基本上是我们的src目录。在这里,我们的工作空间目录必须包含一个名为的文件WORKSPACE,该文件可能引用了构建输出所需的外部依赖关系以及构建规则。

这是一个示例WORKSPACE文件:

在此文件中,有几个依赖项添加到工作区。我们特别声明我们将使用rules_gorules_docker依赖项以及Gazelle,这将帮助我们生成Bazel所需的一些文件。不要担心,如果您不熟悉这种语法,需要一些时间来适应它。

BUILD文件

Bazel有一个关于_包_的概念,它被定义为相关文件的集合以及它们之间依赖关系的规范。如果Bazel工作空间内的目录包含名为的文件BUILD,则会将该目录视为包。包中包含其目录中的所有文件,以及其下的所有子目录,除了那些本身包含BUILD文件的文件。

BUILD文件包含构建规则,这些规则定义了我们应该如何构建包。您可以在此处阅读有关概念和术语的更多信息。

在开始一个新项目时,我们需要做的第一件事是在根目录中添加一个BUILD文件,这将加载稍后用于运行Gazelle with Bazel 的瞪羚规则。

添加此文件后,我们可以使用以下命令运行Gazelle:

这将根据项目中的go文件生成新的BUILD文件。稍后添加新程序和库时,应使用相同的命令更新现有的BUILD文件,否则构建可能会失败。

作为一个例子(基于我们之前显示的项目结构),gazelle将为我们的bar程序生成一个BUILD文件,该文件位于foo包中,如下所示:

现在通过运行命令bazel build //foo/...bazel将构建我们的Go程序并将二进制文件保存在输出目录中。如果要构建整个项目,只需bazel build //...在根文件夹中运行即可。

如果您为您的库和程序(您应该)编写测试,gazelle将为go_test它们生成规则,然后您可以运行bazel test //...将运行所有测试。

Bazel的高级缓存,使运行buildtest命令对整个工作区超级快,因为它只会建造或测试您已更改的文件,以及依赖于这些修改过的文件的文件。

⚠️注意:确保将CI服务器设置为缓存输出目录,否则运行bazel不会带来太多好处。

Docker镜像

在我们想要将二进制文件构建和部署为docker图像的情况下,bazel有一套很好的规则可以做到这一点。更为重要的是,Bazel并不需要Docker拉取,构建或推送镜像。这意味着您可以使用这些规则在Windows / OSX上构建Docker镜像而无需使用docker-machine或者boot2docker也不需要在笔记本电脑上进行_root_访问。

我们bar程序的BUILD文件的完整示例如下所示:

go_image规则使用distroless镜像作为基础,只添加二进制文件作为要运行的命令。container_push如果要将映像推送到远程存储库,也可以使用该规则。

要将二进制文件作为docker镜像运行,只需键入bazel run //foo/cmd/bar:docker命令即可。您还可以构建一个tar包,然后可以使用以下命令手动将其加载到docker中:

  • bazel build //foo/cmd/bar:docker.tar
  • docker load -i bazel-output/foo/cmd/bar/docker.tar

您可以在此处找到有关规则的更多信息。