找回密码
 立即注册
首页 业界区 业界 内网环境下Go module的包管理和包拉取解决方案 ...

内网环境下Go module的包管理和包拉取解决方案

纪晴丽 7 天前
前言

很多开发的小伙伴在工作中经常会遇到需要在内网环境下开发生产,因此就必须要解决内网环境下Go语言的包管理和包拉取问题。恰逢我司前端时间就需要在内网环境下开发新项目,因此在此记录我们内网环境下Go module的包管理和包拉取解决方案,希望给予其他小伙伴有所借鉴。Go 语言在1.16 版本以后已经默认使用 Go Module 模式进行依赖包管理,而Go Module默认使用https://proxy.golang.org作为代理地址来拉取第三方包,但该地址需要能够访问互联网,另外还需要考虑到很多无法直接访问公共的包管理器,如GitHub、Golang.org、Gopkg.in等。
解决方案

在内网环境下,解决Go module的包管理和包拉取的常规解决方案主要有以下几种:

  • 私有代理
在内网中,可以搭建私有的Go module代理服务来缓存、管理和拉取第三方包,以提高包的下载速度,同时解决内网环境下的拉包问题。常用的代理工具有Goproxy、Athens、Nexus等。在搭建好私有代理后,可以设置GOPXOY环境变量来使用私有代理,例如:
  1. $ export GOPROXY = http://172.31.33.33:8080
复制代码

  • Vender目录
可以在项目的根目录下创建vendor目录,将依赖的第三方包直接下载到该目录下。在使用go build、go test等命令时,Go工具链会优先从vendor目录中查找所需的包。在项目根目录下执行以下命令,将当前模块的所有依赖包下载到vendor目录:
  1. $ go mod vendor
复制代码
需要注意的是,endor目录仅适用于项目内的依赖,如果依赖的包又依赖其他第三方包,则需要手动将这些包下载到vendor目录中。同时,如果vendor目录中存在多个版本的同一个包,则需要手动解决冲突。

  • 将依赖包打包到二进制文件中
可以使用go1.16及以上版本的-embed标志,将项目依赖的第三方包打包到二进制文件中,避免在运行时需要依赖外部的包。该方式适用于将应用程序部署到多个环境中,或将应用程序分发给客户端。
  1. $ go build -o app -tags embed -ldflag3="-w -s -extldflags=-static" -embed
复制代码
以上几个就是在内网中进行Go module包管理和包拉取的解决方案,再结合我们实际开发场景,方案2会导致项目整理越来越大,不利于项目的管理、部署和维护,方案3则是只适合再部署时使用,并不能满足正常的工作开发中的需求场景,因此我们选择方案1,通过内部搭建一个私有的go module代理服务来解决内网环境下的拉包问题。
搭建私有go module代理服务

Go module proxy协议规范发布后,Go社区出现了很多成熟的Goproxy开源实现。从最初的athens,再到国内的两个优秀的开源实现:goproxy和goproxy.io等。最终,在考虑到代理服务的部署及维护的方便程度上,我们选择了使用更为简单的goproxy和goproxy.io来搭建私有go module代理服务。
代理服务搭建

goproxy搭建


  • 创建goproxy文件夹,go mod初始化goproxy:
  1. $ go mod init goproxy
复制代码

  • 创建goproxy.go文件,监听本地代理端口,初始化goproxy代理:
  1. package main
  2. import (
  3.         "net/http"
  4.         "github.com/goproxy/goproxy"
  5. )
  6. func main() {
  7.         http.ListenAndServe("localhost:8080", &goproxy.Goproxy{})
  8. }
复制代码

  • 修改GOPROXY环境变量,拉取goproxy服务依赖
  1. $ go env -w GOPROXY=https://goproxy.cn,direct
复制代码

  • 拉取服务依赖,启动goproxy代理服务:
  1. $ cd goproxy
  2. $ go mod tidy
  3. $ go run goproxy.go
复制代码
goproxy.io搭建


  • git clone拉取goproxy.io源码:
  1. $ git clone git@github.com:goproxyio/goproxy.git
复制代码

  • 编译goproxy.io/goproxy下的main.go文件
  1. $ cd goproxy.io/goproxy
  2. $ make
复制代码

  • 命令行启动代理服务
  1. # 直接启动
  2. $ ./bin/goproxy -listen=0.0.0.0:8088 -cacheDir=./modCache -proxy https://goproxy.cn
  3. # 或者已进程方式后台运行时,命令如下:
  4. $ nohup ./bin/goproxy -listen=0.0.0.0:8088 -cacheDir=./modCache -proxy https://goproxy.cn &
复制代码
代理服务使用及测试

搭建好私有代理服务后,我们就可以开始使用代理服务拉取第三方包了。使用go module代理服务很简单,通常情况下,我们都是使用对应的IDE工具来进行代码开发,直接在对应的IDE工具中为对应项目配置代理服务地址。以研发环境下GoLand为例,配置如下:

  • 修改研发机golang环境变量GOPROXY和GONOSUMDB;


  • 修改GOPROXY环境变量,命令如下:
  1. $ go env -w GOPROXY=http://172.31.31.31:2326,direct
复制代码

  • 修改GONOSUMDB环境变量,命令如下:
  1. $ go env -w GONOSUMDB=*
复制代码
默认情况下,当我们执行go get或go mod tidy等命令需要下载模块时,它们会将模块版本和校验和发送到sum.golang.org进行验证,以确保安全性和数据完整性。但由于研发机环境无法连接到环境无法连接到sum.golang.org,因此应该跳过模块的校验和(checksum)验证。
而且,我们拉取的是代理服务器本地的缓存包,本来是已经在代理服务器上通过验证了,因此也可以保证其安全性和完成性。

  • 配置GoLand中的GOPROXY环境变量;
点击Go Module,新增GOPROXY配置项,配置代理服务地址为上述GOPROXY地址。

  • 在代理服务器上清空本地go module缓存,使用代理服务器重新拉取 GO 模块
  1. $ go clean -modcache
  2. $ go mod tidy
复制代码

  • 代理服务器拉包完成后,使用研发机拉取代理机上的包缓存即可
  1. $ go mod tidy
复制代码
针对同一个项目,通过分别配置goproxy和goproxy.io代理服务地址进行测试,最终我们确定goproxy.io会比goproxy更加稳定一些,goproxy经常会以为网络问题出现部分丢包现象,因此我们确定使用goproxy.io来搭建go module私有代理服务。
注意:通过代理服务器拉取go mod,这种方式下,需要保证拉取的go mod依赖包与服务器缓存的依赖包版本一致,否则无法拉取依赖。
参考

私有化仓库的 GO 模块使用实践
小厂内部私有Go module拉取方案
goproxy.cn官方文档
goproxy.io官方文档

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册