不一样的go语言-athens源码概览
前言
上一篇文章介绍了athens私服的安装以及vgo download protocol的简要介绍。本文着重介绍go proxy sever的实现原理以及athens是如何实现的。
go get原理
当GOPROXY没有设置的时候,通过-x参数,可以看到go get获取module的详细过程。
[eventer@localhost]# go get -x github.com/gin-gonic/gin@v1.3.0
对于git来说,go依赖于git命令,通过git命令的组合获取module库的元数据及各版本源码包。而其中的第一步在于向源码仓库获取module的元数据。
[eventer@localhost]# curl -sSL 'https://swtch.com/testmod?go-get=1'
<!DOCTYPE html>
<meta name="go-import" content="swtch.com/testmod mod https://swtch.com/testmodproxy">
Nothing to see here.
go cli根据返回的元数据从指定的地址获取module,说白了就是在本地执行git的各个命令,跟大家平时从源码库拿代码的过程差不多一样。
当GOPROXY被设置的时候,按照《Defining Go Modules》一文中关于proxy server的定义,情况发生了一些变化,而这也正是athens所要实现的内容。
athens概述&流程
按照vgo download protocol中的定义,go proxy server是一个高效、可用、安全,且遵循module格式标准、下载协议、本地缓存以及支持按需下载的代理服务。显然,这是一个构件系统的定义,而athens也正是朝着这个目标实现的。
但由于go get与go mod命令的设定及其主动获取这些特征,使得其与java阵营的nexus、jfrog不同。java的库是由开发者主动deploy到公有仓库或私有仓库中,程序构建的时候再根据pom或gradle配置文件的声明从仓库获取指定的package。而go则省略了第一步,直接在构建的时候由go get或go mod根据go.mod文件的声明从源码库中获取module。因而这就意味着athens首先必须实现从当前流行的源码库中获取公开、私有的module,比如github、gitlab、bitbuckt;又要考虑如何从私有的源码库中获取module。
所以显而易见,athens需要实现的功能列表如下:
功能项 | 性质 | 功能说明 |
---|---|---|
下载协议 | 必需 | 4个必需接口,2个可选接口 |
本地存储 | 必需 | module存储方式,本地磁盘or内存。athens都支持, 可配置 |
云端存储 | 增强 | module存储方式,支持gcp、minio、mongo、s3、AzureBlob,可配置 |
公仓用户认证 | 必需 | github token |
私仓用户认证 | 必需 | SVN、Bazaar、Bitbucket、github、gitlab |
版本控制 | 增强 | 提供方案控制哪些module的哪些版本使用代理、是否可用等 |
日志跟踪 | 增强 | 使用opencensus实现 |
并发控制 | 增强 | 多个并发请求同一个module,处理第一个请求,后续请求等待并获取结果 |
健康检测 | 增强 | 实现服务状态接口 |
管理功能 | 增加 | 实现查询module若干接口 |
那么按照预想,go get指令的流程如下:
而再次获取同一个版本的module时,流程如下:
通过代理取包的过程其实也很简单。athens按照约定,提供了4个或6个接口供go get指令使用。当GOPROXY被设置时,go get切换至新流程,如下(goproxy.io是proxy server):
- https://goproxy.io/github.com/gin-gonic/gin/@v/list
- https://goproxy.io/github.com/gin-gonic/gin/@v/v1.3.0.info
- https://goproxy.io/github.com/gin-gonic/gin/@v/v1.3.0.mod
- https://goproxy.io/github.com/gin-gonic/gin/@v/v1.3.0.zip
这组协议对应至本地文件系统的一组目录$GOPATH/pkg/mod/cache/download,这里保存了对应上述4个接口的文件,这4个文件内容可以到这个目录下自行查看,它们的格式即是协议描述的内容。
接口实现
athens本身是一个web服务,采用gorilla框架实现。main.go位于cmd/proxy包下,关键代码读取配置文件,然后根据配置文件参数初始化程序。
//读入配置文件
conf, err := config.Load(*configFile)
if err != nil {
log.Fatalf("could not load config file: %v", err)
}
//根据配置初始化程序
handler, err := actions.App(conf)
if err != nil {
log.Fatal(err)
}
在app.go文件中,配置了storage、github token、NETRCPath、HGRCPath、log、FilterFile、路由注册。auth.go中的代码将NETRCPath、HGRCPath声明的文件内容转写到当前用户home目录下的预定位置;而关键的路由注册,则由下面的代码完成,调用的是app_proxy.go中的addProxyRoutes方法。
if err := addProxyRoutes(
proxyRouter,
store,
lggr,
conf,
); err != nil {
err = fmt.Errorf("error adding proxy routes (%s)", err)
return nil, err
}
addProxyRoutes方法注册了的路由如下:
路由 | 说明 |
---|---|
/ | 首页 |
/healthz | 健康检测 |
/readyz | - |
/version | athens版本 |
/catalog | 所有module列表 |
在这之后,定义了GoGetFetter用于处理module的下载、upstream vcs监听器、并发控制器、vgo download protocol协议实现。
handlerOpts := &download.HandlerOpts{Protocol: dp, Logger: l}
//RegisterHanlders方法注册了list、version.info、version.mod、version.zip这4个接口的路由
download.RegisterHandlers(r, handlerOpts)
athens包说明:
包 | 用途 | 描述 |
---|---|---|
pkg/config | 配置文件对应实体 | 存取配置文件参数 |
pkg/download/ | vgo download protocol协议实现 | 核心入口 |
pkg/errors | errors统一定义及堆栈跟踪 | 良好的错误设计,可以快速定位到出错的包、方法 |
pkg/log | logrus日志框架集成 | - |
pkg/middleware | 中间件 | module缓存、日志、请求验证、module获取策略 |
pkg/module | module获取策略、仓库源码获取、zip获取实现 | - |
pkg/observ | 日志及统计数据输出 | datadog |
pkg/paths | module path解析工具 | - |
pkg/stash | module获取与存储包装类及module并发请求控制 | - |
pkg/storage | 存储实现 | 包括内存、本地磁盘、数据库(mongodb)、文件系统(afero抽象文件系统)、云存储(s3,gcp,minio)等 |
module获取策略:
项 | 定义 | 说明 |
---|---|---|
module.Exclude | 排除 | 忽略对指定包的请求 |
module.Include | - | 不走代理,按常规模式获取包,本地私仓使用此配置 |
module.Direct | - | 走代理 |
获取module流程图:
在athens的实现中,各个包之间的调用关系如下:
GET baseURL/module/@v/list时序图:
GET baseURL/module/@v/version.info时序图:
baseURL/module/@v/version.mod与baseURL/module/@v/version.zip的过程与baseURL/module/@v/version.info一致,只是调用不同的实现而已。
欢迎关注个人公众号
不一样的go语言-athens源码概览的更多相关文章
- go语言nsq源码解读八 http.go、http_server.go
这篇讲另两个文件http.go.http_server.go,这两个文件和第六讲go语言nsq源码解读六 tcp.go.tcp_server.go里的两个文件是相对应的.那两个文件用于处理tcp请求, ...
- (转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin
转自:http://www.baiyuxiong.com/?p=886 ---------------------------------------------------------------- ...
- c语言memset源码
c语言memset源码 一.用法 void *memset(void *s, int ch, size_t n);作用:将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的 ...
- spring源码概览
阅读spring源码需要具备的基本技能: 1,设计模式(工厂模式,单例模式,代理模式,模板模式,观察者模式,装饰器模式,适配器模式) 2,数据结构和算法(栈,队列,树以及一些基本的算法) 3,反射(如 ...
- go语言nsq源码解读七 lookup_protocol_v1.go
本篇将解读nsqlookup处理tcp请求的核心代码文件lookup_protocol_v1.go. 1234567891011121314151617181920212223242526272829 ...
- go语言nsq源码解读一-基本介绍
简单介绍一下nsq. 参考 http://feilong.me/2013/05/nsq-realtime-message-processing-system 的介绍:NSQ是由知名短链接服务商bitl ...
- go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin
nsqlookupd: 官方文档解释见:http://bitly.github.io/nsq/components/nsqlookupd.html 用官方话来讲是:nsqlookupd管理拓扑信息,客 ...
- go语言 nsq源码解读三 nsqlookupd源码nsqlookupd.go
从本节开始,将逐步阅读nsq各模块的代码. 读一份代码,我的思路一般是: 1.了解用法,知道了怎么使用,对理解代码有宏观上有很大帮助. 2.了解各大模块的功能特点,同时再想想,如果让自己来实现这些模块 ...
- 网易2017校园招聘算法题c语言实现源码
题目: 给定一个数组,除了一个数出现1次之外,其余数都出现3次.找出出现一次的数.如:{1, 2, 1, 2, 1, 2, 7}, 找出7. 格式: 第一行输入一个数n,代表数组的长度,接下来一行输入 ...
随机推荐
- learning java 文件锁
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; i ...
- ServiceStack.OrmLite 基本操作
原文:https://www.cnblogs.com/wang2650/category/780821.html 原文:https://www.cnblogs.com/xxfcz/p/7045808. ...
- Web前端鼠标悬停实现显示与隐藏效果
css定义,偏移量,相对定位,绝对定位 显示与隐藏 二维码相对于微信图标定位 鼠标悬停微信图标上显示 鼠标离开微信图标时隐藏 什么是定位,就是定义网页标签在运行时显示的位置 css提供Position ...
- vue 进入页面与离开页面触发事件
1.切换进入当前路由之前的钩子函数 beforeRouteEnter <script> export default { beforeRouteEnter(to, form, next) ...
- Promise链式调用 终止或取消
Promise回调分两种方法,then成功,catch失败 let promise = new Promise(function(resolve, reject){ resolve('第一次成功') ...
- jmeter接口自动化和性能学习目录
目录黑色代表未完成的,绿色代表已完成的文章.目录的作用的为了引导和总结自己的学习,也是为了更好的分享给大家. 一.接口自动化 jmeter解决登录token获取 jmeter五种提取器 之 正则表达 ...
- NFV实验平台
NFV架构如下图所示. NFVI对应于数据平面,数据平面转发数据并提供用于运行网络服务的资源. MANO对应于控制平面,该控制平面负责构建各种VNF之间的连接以及编排NFVI中的资源. VNF层对应于 ...
- pm升级到最新版本、指定版本
npm 升级到最新版本 //linux下 npm install -g npm npm升级到指定版本 //比如升级到5.6.0 npm install -g npm@5.6.0
- 啃OBS源码-界面汉字
插件对应该字体目录:D:\project\vs\obs\obsstudio21.12\build\rundir\Debug\data\obs-plugins obs对应该字体目录:D:\project ...
- 开启Nginx监控 with-http_stub_status_module
1.开启监控with-http_stub_status_module ./configure --with-openssl=/usr/local/ssl --with-http_stub_stat ...