21

为 Go module 搭建私服

 5 years ago
source link: http://blog.cyeam.com/golang/2018/09/27/athens?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

之前介绍了如何在线上环境打包,这样能解决问题,但是由于是借助代理下载依赖包,打包的过程偏慢,我自己的感觉打一个项目需要2分钟所有。而且还有一个严重问题,那就是一旦下载失败,打包就失败了,还得重试。这个体验很不好。关于 Go module 打包,我感觉未来的发展方向还是和 Java 的一样,得自己整私服,这样打包会很快,而且也安全。我们打包从私服下载,私服如果缓存了当前版本的包,直接返回;否则私服去下载对应版本的代码。

私服安装

首先你需要安装 Go1.11。

我用的是 Athens ,雅典娜。

首先下载代码:

git clone https://github.com/gomods/athens
cd athens

即使用私服还是得设置代理:

export HTTP_PROXY=10.244.255.3:7766
export HTTPS_PROXY=10.244.255.3:7766

编译安装二进制文件:

go install

启动

因为是通过 go install 安装,所以会被安到 $GOBIN 里,它会是全局的可以直接调用。

./proxy

但是这样太简陋了,我用 Supervisor 来做进程守护,配置文件如下:

[program:proxy]
command=/path/to/proxy -config_file=/path/to/github.com/gomods/athens/config.dev.toml
environment=HTTP_PROXY="10.244.255.3:7766",HTTPS_PROXY="10.244.255.3:7766"
stdout_logfile=/tmp/proxy.log
stderr_logfile=/tmp/proxy.log
autostart=true
autorestart=true
startsecs=5
priority=1
stopasgroup=true
illasgroup=true

打包脚本

之前是四行脚本,这次变了两行:

export GO111MODULE=on
export GOPROXY=http://127.0.0.1:3000

打包开始后,私服的日志能看到类似于这样的日志:

handler: GET /github.com/spf13/afero/@v/v1.1.1.zip [200]

而打包日志是这样:

go: downloading github.com/spf13/pflag v1.0.2

如果是第一次下载,会有可能超时:

go: gopkg.in/[email protected]: unexpected status (http://10.244.255.3:7766/gopkg.in/tomb.v1/@v/v1.0.0-20141024135613-dd632973f1e7.info): 500 Internal Server Error

这样没事,稍等一会就会好,可以把上面的链接放到浏览器里面刷一下,能刷出来结果那说明下载好了。

{
	"Version": "v1.0.0-20141024135613-dd632973f1e7",
	"Time": "2014-10-24T13:56:13Z"
}

GOPROXY

其实最核心的是上面的 GOPROXY ,这个是 Go 官方的代理设置,和 HTTP_PROXY 不一样哦。

可以使用命令 go help goproxy 查看详细介绍,也可以看 这里

Go module 支持通过代理的方式下载,如果环境变量 GOPROXY 设置了,所有的包都会从这个代理下载。

代理基于 HTTP 协议的 GET 方法,请求的时候没有参数,所以只要是符合固定的规则,任何服务器都可以做代理服务器。比如一个静态文件服务器。

规则是:

GET $GOPROXY/ /@v/list 返回所有已知的当前 module 的版本号,每行一条

GET /github.com/mnhkahn/gogogo/@v/list
v1.0.0
v1.0.1
v1.0.2
v1.0.3
v1.0.4
v1.0.5

GET $GOPROXY/ /@v/ .info 返回 JSON 格式的版本元数据

GET /github.com/mnhkahn/gogogo/@v/v1.0.5.info
{
	"Version": "v1.0.5",
	"Time": "2018-09-26T02:47:43Z"
}

元数据的 Go 结构体定义:

type Info struct {
    Version string    // version string
    Time    time.Time // commit time
}

GET $GOPROXY/ /@v/ .mod 返回这个 module 版本的 go.mod 文件

GET /github.com/mnhkahn/gogogo/@v/v1.0.5.mod
module github.com/mnhkahn/gogogo

require (
	github.com/BurntSushi/toml v0.3.0 // indirect
	github.com/ChimeraCoder/gojson v1.0.0
	github.com/davecgh/go-spew v1.1.1 // indirect
	github.com/magiconair/properties v1.8.0
	github.com/pmezard/go-difflib v1.0.0 // indirect
	github.com/sasbury/mini v0.0.0-20161224193750-64bd399395db
	github.com/stretchr/testify v1.2.2
	golang.org/x/net v0.0.0-20180826012351-8a410e7b638d
	gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3
	gopkg.in/yaml.v2 v2.2.1 // indirect
)

GET $GOPROXY/ /@v/ .zip 返回这个 module 对应版本的 zip 压缩包。

GET /github.com/mnhkahn/gogogo/@v/v1.0.5.mod
v1.0.5.zip

所有的包名会被编码成小写。如果有大写字母,前面加感叹号。

github.com/Azure => github.com/!azure

Athens 的实现

下载的时候会读取这些环境变量:

func PrepareEnv(gopath string) []string {
	pathEnv := fmt.Sprintf("PATH=%s", os.Getenv("PATH"))
	httpProxy := fmt.Sprintf("HTTP_PROXY=%s", os.Getenv("HTTP_PROXY"))
	httpsProxy := fmt.Sprintf("HTTPS_PROXY=%s", os.Getenv("HTTPS_PROXY"))
	noProxy := fmt.Sprintf("NO_PROXY=%s", os.Getenv("NO_PROXY"))
	gopathEnv := fmt.Sprintf("GOPATH=%s", gopath)
	cacheEnv := fmt.Sprintf("GOCACHE=%s", filepath.Join(gopath, "cache"))
	disableCgo := "CGO_ENABLED=0"
	enableGoModules := "GO111MODULE=on"
	...
}

HTTP_PROXYHTTPS_PROXY 是私服下载包的时候会用到的代理设置,而 NO_PROXY 可以加不走代理的白名单:

export NO_PROXY=gopkg.in,$NO_PROXY

这些环境变量会被作为临时环境变量用于代码的下载。而下载依赖包的逻辑:

cmd := exec.Command(goBinaryName, "mod", "download", fullURI)
cmd.Env = PrepareEnv(gopath)
cmd.Dir = repoRoot
o, err := cmd.CombinedOutput()

实际执行时就是:

HTTP_PROXY=10.244.255.3:7766 HTTPS_PROXY=10.244.255.3:7766 GOPATH=/tmp/athens167327692 GOCACHE=/tmp/athens167327692/cache go mod download golang.org/x/[email protected]

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK