背景     



Go 语言是 Google 开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。为了方便搜索和识别,有时会将其称为 Golang。自2009年11月 Google 正式宣布推出,成为开放源代码项目以来,Go 语言已成为当今开发人员和 DevOp s领域最流行的语言之一, 它被用于设计和编写 Kubernetes 和 Helm。


但是,相比语言本身已经得到了广泛的普及和使用,Go 语言的包管理方案却大大滞后了。2018年 Google 终于在Go1.11官方推出了 Go modules,为 Go 语言提供了支持版本化的依赖管理方案。


Go modules 现在已成为 Go 语言标准的依赖管理工具和包仓库规范。而 GoCenter 为 Go modules 的实现和推广提供了依赖包的公共仓库,使得 Go 语言的开发人员能够更为稳定和方便地开发可重复构建的 Go 应用程序。


除了提供 Go 仓库外,在获取和下载 Go module 包方面,GoCenter 提供了比传统的如 GitHub 等版本管理系统更为快速的支持。



  验证 GoCenter 速度的测试  



为了验证 GoCenter 提供了更快获取 Go modules 的方式,我们设计了如下测试方案:


1、我们选取了两个 Go 项目,用以比较不同项目规模下速度的不同。


一个是私有项目,webhook-bridge

https://github.com/retgits/webhook-bridge)

一个是公共项目,静态站点生成器 Hugo

(https://github.com/gohugoio/hugo)


2、我们在两个网络环境下分别执行测试,用以比较不同网络条件下速度的不同。一个是 JFrog 的公司网络,一个是家庭网络。


3、构建 Go 项目通常包含两步,第一是下载依赖,第二是编译可执行程序


本次测试集中在第一部分,Go 包的下载速度。为了使测试尽可能公平和不间断, 我们编写了一个脚本, 在运行“go get”之前删除了所有模块,然后对于同一个项目分别使用 GitHub 和 GoCenter 来获取依赖。这些命令将运行10次, 结果记录在文件中。


测试使用的脚本参见https://github.com/xingao0803/GoCenter-Performance/blob/master/testscript.sh。


同时,为了保证测试的公正性,我们测试的时候并没有通知 GoCenter 团队。他们既不能对测试所用的项目或模块产生影响,也无法篡改我们的测试数据。



 测试结果 


测试结果的详细列表参见https://github.com/xingao0803/GoCenter-Performance/blob/master/GoCenter-performance.xlsx


在这里,我们统计一下,列出每个项目的最快和最慢运行之间的差异。


1. 私有项目的测试结果

在 JFrog 公司网络测试私有项目:

GoCenter 为 Go moudles 加速_java

在家庭网络测试私有项目:

GoCenter 为 Go moudles 加速_java_02

最后一列“总运行时间”,是测试下载 Go 项目依赖包并放入正确位置的时间。从上述统计可以看出,通过 GoCenter 获取 Go modules 依赖比从 GitHub 获取速度更快,消耗资源更少。


这个私有项目只有6个直接依赖和12个间接依赖的 Go module。如果使用更大规模的项目,如 Hugo,包括43个直接依赖和11个间接依赖,效果又会如何呢?


2. Hugo项目的测试结果

在 JFrog 公司网络测试私有项目:

GoCenter 为 Go moudles 加速_java_03

在家庭网络测试私有项目:

GoCenter 为 Go moudles 加速_java_04

从上述统计可以看出,对于大型 Go 项目,虽然 CPU 占比相对较高,但是从 GoCenter 获取依赖的速度相对更快了。


3. 测试总结

通过上述针对测试结果的分析和统计,不难看出,使用GoCenter 获取 Go modules 依赖,比直接从 GitHub 等版本控制系统获取这些依赖速度更快,而且还节省了 CPU 周期。而且,随着项目复杂性的增长(更大的依赖树),性能的提升更为明显。



 分析GoCenter快速的原因 


要了解 GoCenter 速度更快的原因,我们需要深入分析 go客户端是如何获取 Go modules 依赖包的。我们来比较一下,在是否设置 GOPROXY 变量的情况下,执行 go get 获取 modules 有什么不同?


1. 获取module信息

第一个区别从 “import” 库开始。使用 Go 编写的每一个应用都会使用库。这些库可能是标准库,如 “fmt” 或 “io”,也可能是由别处分享的。


如果没有设置 GOPROXY 变量,且项目包位于任意预定义好的版本控制系统(如 GitHub),Go 客户端会知道如何解析 URL 以获取相关模块。如果项目包不在这些系统中,Go 客户端将会执行动态 HTML 检查,来查找表明如何、以及在何处获取相关模块的元数据标记。这个过程需要 HTTP 重定向和 HTML 解析。


如果设置 GOPORXY 变量指向 GoCenter,Go 客户端就会向 GoCenter 发送一个请求来获取 module 信息。GoCenter 更快速的第一个原因就在于不需要复杂的 HTML和 HTTP 处理,而是直接使用一个简单的 HTTP 请求。这个优势在大量依赖存活在预定义的版本控制系统之外的 Go 项目上会显得更为突出。


2. 下载 module

下一步是要把相关 module 下载到本地。Go module 已被打包成 zip 文件,以及少数附加的元数据文件(我们稍后讨论)。


如果不设置 GOPROXY 变量,Go 客户端将执行 “git clone”,并在 $GOPATH/pkg/mod/cache/vcs 目录创建一个 “bare” 仓库。


如果将 GOPROXY 变量设置为 GoCenter,Go 客户端将会发送 HTTP GET 请求并下载 zip 文件。GoCenter 赢得速度的第二点就在于,下载文件通常比执行 “git clone” 快得多。在这种情况下,由于 Go module 是压缩好的文本文件,下载会节省更多的时间和带宽。


3. 构建 module

接下来要构建 module,以便在 Go 应用中使用。 如前所述,Go module 是带附属文件的 zip 压缩包,这些附属文件包括 .info(包含版本号和提交时间)和 .mod(下载的 module 文件)等。Go 客户端需要这些文件及其实际来源。


如果没有设置 GOPROXY 变量,Go 客户端需要计算并生成这些文件,再把他们和 module 文件一起放到$GOPATH/pkg/mod/cache/download 文件夹。稍后还需要把他们移动到 $GOPATH/mod/<vcs>/<module> 文件夹。


如果 GOPROXY 已设置为 GoCenter,这些文件已经随之前的下载并放到 $GOPATH/pkg/mod/cache/download 里。Go 客户端只需简单地解压 zip 文件,然后把源文件(不带元数据文件)放到 $GOPATH/mod/<vcs>/<module>。解压文件可比计算校验和、生成文件,并获取 “bare” 仓库的副本要快得多了,这正是 GoCenter 的第三个速度优势。


4.总结

我们总结一下。当不设置 GOPROXY 时,Go 客户端采取的步骤是:


  • 寻找module的位置以及访问协议,这可能需要额外的HTTP和HTML处理


  • 执行 “git clone”,并在 $GOPATH/pkg/mod/cache/vcs 创建 “bare” 仓库


  • 生成 zip 文件,计算校验和,生成元数据文件,并把它们放到 $GOPATH/pkg/mod/cache/download


  • 把不带元数据文件的源文件放到$GOPATH/mod/<vcs>/<module>


  • 而设置 GOPROXY 为 GoCenter 后,Go 客户端的工作就简化了很多


  • 下载module的 .mod、.info 和 .zip 文件,并放到$GOPATH/pkg/mode/cache/download(只有3个 HTTP GET操作)


  • 把源文件解压到 $GOPATH/mod/<vcs>/<module>


通过使用 GoCenter,去掉了查找 module 的 HTTP 和 HTML 处理,“昂贵”的源码 clone 操作,以及元数据文件的生成操作。


    总结    

Go 语言是目前最为流行的编程语言之一,而 Go modules 的推出为 Go 语言增加了完善的依赖管理方案。


JFrog 推出的 GoCenter,做为 Go modules 的中央仓库,为广大的 Go 开发者提供了丰富的、版本化管理的公共 Go modules 包。


除此之外,因为在下载文件是采用正确的协议、节省 HTTP调用次数,以及无需在客户端重新创建模块等特性, GoCenter 还为 Go modules 的应用提供了更快速的支持。


我们针对 GoCente r的支持速度进行了测试,结果验证了我们的预期。这一测试结果在 Go 社区也得到了众多正面回应。我们测试所用的项目、脚本,以及测试结果都在前文中列出,欢迎大家自己实际操作、验证一下。


想要了解有关 GoCenter 更多深入的技术信息?

请查看 GoCenter 的 Github 项目https://github.com/jfrog/gocenter