关注世界领先 DevOps 平台 JFrog
背景
Go 语言是 Google 开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。为了方便搜索和识别,有时会将其称为 Golang。自2009年11月 Google 正式宣布推出,成为开放源代码项目以来,Go 语言已成为当今开发人员和 DevOps 领域最流行的语言之一, 它被用于设计和编写 Kubernetes 和 Helm。但是,相比语言本身已经得到了广泛的普及和使用,Go 语言的包管理方案却大大滞后了。
Go 语言生态系统中缺少的是标准化——没有用于依赖关系管理的标准工具, 也没有标准的包格式或兼容的包仓库规范。这意味着开发人员无法使用 Go 语言创建可重现的构建, 这是一个相当大的问题。这些年来, 社区推出了诸如 dep、godep、glide 和 govender 等工具,试图用来处理 Go 语言的依赖管理, 但并未成功。2018年 Google 在 Go1.11官方推出了 Go modules,为 Go 语言提供了支持版本化的依赖管理方案。
Go modules 现在已成为 Go 语言标准的依赖管理工具和包仓库规范。而 GoCenter 为 Go modules 的实现和推广提供了依赖包的公共仓库,使得 Go 语言的开发人员能够更为稳定和方便地开发可重复构建的 Go 应用程序。
Go语言的依赖管理
在介绍 GoCenter 之前,我们先简要地回顾一下 Go 语言依赖管理的发展历程。
Go 语言在推出之初,并没有明确的依赖管理方案。只是在构建过程中通过 go get 命令,将用 import 声明的依赖从对应的源,通常是 git 上的项目,下载到 $GOPATH/src 目录下,和 Go 应用自身的代码放在一起。这种依靠 GOPATH 来管理依赖的机制带来的问题 是显而易见的,比如:
因源依赖包自身的变化,导致不同时间构建 Go 应用时 go get 得到的依赖实质上是不同的,即不能实现可重复的构建;
或者因源依赖包自身的变化,重新构建 Go 应用时会引入不兼容的新实现,导致 Go 应用无法通过编译。
因此在1.5版本以前,为了规避这个问题,通常需要将使用的依赖包手工拷贝出来。
为了实现 Go 应用的可重复构建,Go1.5引入了 Vendor 机制。Vendor 机制的核心就是在 GOPATH 下面增加了 vendor 文件夹。Go 应用所需的依赖都可以从依赖源 fork 出所需的分支,存放到 vendor 文件夹。当构建 Go 应用时,Go 编译器会优先在 vendor 文件夹下搜索依赖的第三方包,vendor 文件夹下没有才会再到 $GOPATH/src 下去找。这样只要开发者预先将特定版本的依赖包存放在 vendor 文件夹,并提交到 Go 项目的 code repo,那么所有人理论上都会得到同样的编译结果,从而实现可重复构建。 在 Go1.5发布后的若干年,Go 社区把注意力都集中在如何利用 Vendor 机制解决 Go 应用的依赖管理问题,并诞生了众多的依赖管理工具,如 dep、golide、govendor 等。然而,和 Java 的 Maven、Python 的 Pypi、C/C++ 的 Conan 等业界成熟的依赖管理方案相比,Vender 机制仍然存在许多问题,比如:
Vendor 文件夹中的依赖包没有版本信息。这样依赖包脱离了版本管理,对于一致性管理、升级,以及问题追溯等场景,都会难以处理;
Vendor 机制没有给出如何能够方便地得到 Go 项目依赖了哪些包,并将其拷贝到 vendor 文件夹下的方案,多数情况下还需要到不同的 Git 源项目里手工拷贝;
当依赖的包比较多的时候,vendor 文件夹也会变得非常庞大。
2018年年初,Go 核心 Team 的技术 leader,也是 Go Team 最早期成员之一的 Russ Cox 在个人博客上连续发表了七篇文章,系统阐述了 Go team 解决“包依赖管理”的技术方案:vgo。Vgo 的主要思路包括:语义导入版本控制(Semantic Import Versioning)、最小版本选择(Minimal Version Selection)、以及引入 Go module 等。同年5月份,Russ Cox 的提案“cmd/go: add package version support to Go toolchain”被社区接受,vgo 的代码合并到 Go 主干,并将这套机制正式命名为“go modules”。由于 vgo 项目本身就是一个实验原型,merge 到主干后,vgo 这个术语以及 vgo 项目的使命也就此结束了。后续 Go modules 机制将直接在 Go 主干上继续演化。
Go modules 机制的主要变化包括:
去除了饱受诟病的 GOPATH 的限制。Go 编译器将不再到 GOPATH 下面的 vendor 或 src 文件夹下搜索 Go 应用构建依赖的第三方包;
Go modules 机制为在同一应用 repo 下面的包赋予了一个新的抽象概念: 模块(module),即可重用的 Go 代码包,并启用一个新的文件 go.mod 记录模块的元信息和依赖关系。而在 go.mod 里明确描述了依赖包的版本信息,同一个依赖包也可以记录多个不同的版本。除了精确版本外,go.mod 还支持用表达式模糊地定义依赖版本;
在 Go modules 机制下,还支持创建 Go 依赖包的公共仓库。这是因为应用程序包含的 Go 模块,必须从数千个独立的源代码存储库中解析,而每个存储库的维护纪律可能各不相同。因此,需要存在一个可公开访问的存储库,通过 Go modules 提供的依赖描述、解析机制,为 Go 的开发者提供一致的、可分享的、支持重复构建的、稳定的 Go 依赖包源。GoCenter 就是这种 Go 依赖包公共仓库的重要实现。
GoCenter 简介
GoCenter 通过创建 Go 模块的公共中央仓库,提供可重复和快速依赖解析的依赖包管理方案,解决了 Go 开发人员查找和获取 Go 依赖包的困难。GoCenter 将直接从源代码存储库获取 Go 项目,转变为处理和验证不可变的、具备版本控制的 Go 模块, 并将其免费提供给 Go 应用的开发人员。
GoCenter(https://gocenter.io)提供了通过公共 Go 代理解析模块, 包括通过托管免费服务搜索模块的能力。从创建开始, GoCenter 已经包括了数千个广受欢迎的 Go 项目的模块, Go 开发者可以立即使用这些项目进行自己的构建。
开发人员也可以提交自己的 Go 项目加入 GoCenter,以便将其提供给 Go 社区开发者,从而得到更为广泛地应用。
GoCenter 这个中央仓库,提供了预先打包,以及版本化的 Go 模块,使得 Go 开发人员或团队不再需要为使用公共模块而构建自己的模块库, 从而消减了使用 Go 语言的巨大成本。
此外,如果 Go 开发者或团队已经有了自己的 JFrog Artifactory 仓库,就可以通过配置指向 GoCenter 的远程仓库,为重复构建提供完全的本地化控制,并可以预防访问 GoCenter 的网络连接问题。
基于 GoCenter 构建 Go 应用
要构建 Go 应用项目,首先需要安装 Go 客户端(版本1.11.0 或更新的版本) 。而安装Go 之后,有三种方法可以从 GoCenter 解析 Go 模块:使用 goc、使用 go 客户端,或部署本地仓库(如Artifactory),以代理 GoCenter。
1. 使用 goc
推荐在构建中使用 GoCenter 的方式是通过 goc 工具。Goc 工具包装了 Go 的客户端,器, 能够使用 GoCenter 中的包正确构建 Go 应用,而无需手动设置。
要安装 goc,需要使用以下的 curl 命令,或按照 goc 的 github 主页(https://github.com/jfrog/goc)的说明:
$ curl -fL https://getgoc.gocenter.io | sh
然后, 就可以从 Go 项目的根目录中运行任何命令, 就像运行 Go 命令一样。例如:
$ goc build
Goc 工具自动分配 GOPROXY 连接 GoCenter,所以能够优先从该仓库解析 Go 的依赖包。对于在 GoCenter 找不到的包,goc 将会试图通过源代码控制系统来解析它们,以更好地保证成功构建 Go 项目。
Go 客户端自身不能执行这种辅助操作(请参阅下文), 因此至少在 GoCenter 能够为大多数 Go 开发人员提供可能需要的所有依赖之前,仍然建议使用 goc。
2. 使用 Go 客户端
推荐在构建中使用 GoCenter 的方式是通过 goc 工具。Goc 工具包装了 Go 的客户端,器, 能够使用 GoCenter 中的包正确构建 Go 应用,而无需手动设置。
如上所述,使用 GoCenter 时并不建议直接利用 Go 客户端进行构建,因为当在GoCenter找不到相关依赖包时构建会失败。对于 Go 客户端这种限制的详细信息,可以参考相关的 issue 和修正信息(https://github.com/golang/go/issues/26334)。Go 开发人员还是应该改用 goc。
当然,如果在充分了解这个限制还希望使用的情况下,也是可以使用 Go 客户端的。
如果希望构建 Go 项目时从 GoCenter 中获取相关依赖包,需要设置 GOPROXY 指向GoCenter 的 URL,https://gocenter.io:
$ export GOPROXY=https://gocenter.io
现在就可以使用 Go 客户端构建 Go 应用了:
$ go build
3. 部署代理 GoCenter 的私有仓库
如果使用的是如 Artifactory 这样的私有仓库,则只需设置 GOPROXY 指向该私有仓库,而把 GoCenter 创建为该私有仓库当中的远程仓库。
为了要在 Artifactory 里创建代理 GoCenter 的远程仓库,需要遵循以下步骤:
创建新的远程仓库,并设置包类型为 Go;
设置远程仓库的名字,并在 URL 字段输入https://gocenter.io/;
点击“保存 & 完成”按键。
还可以创建虚拟仓库,用以聚合同时从本地 Go 仓库和远程仓库获取的 Go 依赖包。
一旦在 Artifactory 里配置好使用 GoCenter,就可以使用标准的 GOPROXY 方式基于Artifactory 进行构建。需要注意的是,根据 Artifacotry 上的设置,需要适当地处理客户端的认证信息,应为当前 Go 客户端在获取模块时是不会发送相关认证信息的,所以处理起来是有一定难度的。因此,当使用 Artifactory 代理 GoCenter 时,建议使用 JFrog CLI 来构建 Go 应用。当配置好 JFrog CLI 和 Artifactory 的关联之后,就可以使用类似于
“jfrog rt go build”的命令来从 Artifactory 获取依赖,并构建 Go 应用。
使用 JFrog CLI 的好处是可以方便地向 Artifactory 上传针对特定构建而创建的依赖包,也同时内置支持生成和发布与构建过程相关的元数据。详细信息,请参考 JFrog CLI 的相关文档。
搜索 Go 模块
GoCenter 首页中的搜索框可帮助按特定模块名称(例如, "虹膜")进行搜索。当执行搜索时,GoCenter 将列出与搜索名称匹配或部分匹配的模块。
点击列表中的某个模块,将会列出 GoCenter 中该模块的所有版本:
列出的版本都利用颜色编码来指示其当前的可用状态:
绿色,表示该模块版本已在 GoCenter 之中且处于可用状态;
红色,表示该模块版本不存在,而且不可用;
灰色,表示该模块版本正在引入的过程中,尚未可用。
搜索结果还会显示那些 Go 项目在相关 Git 代码库存在,而在 GoCenter 尚不存在的模块版本列表。如果有这样的缺失版本,可以通过单击 “Add missing version(s)” 把它们 添加到 GoCenter。
提交自己的 Go 模块
如果希望将自己的 Go 项目添加到 GoCenter,使其可被 Go 社区的开发人员使用,则需要提交相关的加入申请。
首先可以对希望加入的模块名执行搜索。如果相关模块并不存在,则可以单击“Add”图标来请求添加模块。一旦点击,将会看到加入申请表格。在表格中,可以输入申请加入的 Go 模块的 URL。通过搜索该模块的结果可以查看该模块的加入进度。
GoCenter 将依据以下最低标准来验证加入请求:
Go 模块位于 gihub.com 或 gopkg.in 上的公共项目(repo);
该项目没有被设置为存档状态(archived);
该项目至少拥有3颗星
总结
自从2007年首次在谷歌构想,并于2009年正式推出,Go 语言很快就成为最流行的编程语言之一。事实上,Helm 和 Kubernetes 都是用 Go 语言编写的。在2017年的一项调查中,Go 语言在开发者的偏好中排名最高,67%的开发者都在利用 Go 语言编程。
为此, 我们期望 GoCenter 能够为不断增长的 Go 社区和开发人员提供必要的服务,并帮助 Go 语言更加符合 DevOps 的需求。
通过访问 GoCenter,https://gocenter.io,可以发现经常使用的 Go 依赖包都已经包含在其中了。如果还没有,请提交相关的加入申请。
GoCenter 管理了版本化的 Go 模块,可以和 Go 应用构建使用的任何 CI 服务器或私有仓库进行对接。而使用 JFrog CLI 和 Artifactory,可以使得这一过程更加便捷。
想要了解有关 GoCenter 更多深入的技术信息?请查看 GoCenter 的 Github 项目,https://github.com/jfrog/gocenter。
参考文献
Golang:https://golang.org
Go & Versioning: https://research.swtch.com/vgo
GoCenter:https://gocenter.io/
https://github.com/jfrog/gocenter。
goc: https://github.com/jfrog/goc
JFrog CLI:https://www.jfrog.com/confluence/display/CLI/CLI+for+JFrog+Artifactory
联系我们:info@jfrogchina.com
点击“阅读原文” 进入 JFrog 官网
有疑问加站长微信联系(非本文作者)