不一样的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,代表数组的长度,接下来一行输入 ...
 
随机推荐
- Python爬虫进阶 | 多线程
			
一.简介 为了提高爬虫程序效率,由于python解释器GIL,导致同一进程中即使有多个线程,实际上也只会有一个线程在运行,但通过request.get发送请求获取响应时有阻塞,所以采用了多线程依然可以 ...
 - java代码操作Redis
			
1.导入需要的pom依赖 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEn ...
 - 23-ESP8266 SDK开发基础入门篇--编写Android TCP客户端 , 加入消息处理
			
https://www.cnblogs.com/yangfengwu/p/11203546.html 先做接收消息 然后接着 public class MainActivity extends App ...
 - 表单提交 curl和浏览器方式
			
表单被提交时,每个表单域都会被Url编码之后才在被发送. 浏览器每次向服务器发送url时,会进行编码,然后web服务器再进行解码. 所以,理论上,curl模拟登陆时,所传参数都必须urlencode一 ...
 - x64内核强删文件.
			
目录 x64内核中强删文件的实现 一丶简介 1.步骤 2.Nt驱动代码 x64内核中强删文件的实现 一丶简介 说道删除文件.有各种各样的方法. 有ring3 也有ring0. 而且也有许多对抗的方法. ...
 - mysql pi() 获取pi
			
mysql> select pi(); +----------+ | pi() | +----------+ | 3.141593 | +----------+ row in set (0.00 ...
 - MATLAB关闭科学计数法显示
 - 欢迎来到地狱 WriteUp(2019暑假CTF第一周misc)
			
目录 0707,0708,0709 题目地址:欢迎来到地狱 1.地狱伊始.jpg 1.5地狱之声.wav 2.第二层地狱.docx 3.快到终点了.zip 参考 0707,0708,0709 题目地址 ...
 - mysql增删改查sql语句
			
未经允许,禁止转载!!!未经允许,禁止转载!!! 创建表 create table 表名删除表 drop table 表名修改表名 rename table 旧表名 to 新表名字创建数 ...
 - ip地址掩码和位数对应关系表、子网掩码、网络地址、主机地址-yellowcong
			
本文链接:https://blog.csdn.net/yelllowcong/article/details/76736594ip的地址掩码,刚开始感觉特别蒙蔽,网掩码都是每段8位二进制,共32位,子 ...