前言

  上一篇文章介绍了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):

  1. https://goproxy.io/github.com/gin-gonic/gin/@v/list
  2. https://goproxy.io/github.com/gin-gonic/gin/@v/v1.3.0.info
  3. https://goproxy.io/github.com/gin-gonic/gin/@v/v1.3.0.mod
  4. 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源码概览的更多相关文章

  1. go语言nsq源码解读八 http.go、http_server.go

    这篇讲另两个文件http.go.http_server.go,这两个文件和第六讲go语言nsq源码解读六 tcp.go.tcp_server.go里的两个文件是相对应的.那两个文件用于处理tcp请求, ...

  2. (转)go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin

    转自:http://www.baiyuxiong.com/?p=886 ---------------------------------------------------------------- ...

  3. c语言memset源码

    c语言memset源码 一.用法 void *memset(void *s, int ch, size_t n);作用:将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值, 块的 ...

  4. spring源码概览

    阅读spring源码需要具备的基本技能: 1,设计模式(工厂模式,单例模式,代理模式,模板模式,观察者模式,装饰器模式,适配器模式) 2,数据结构和算法(栈,队列,树以及一些基本的算法) 3,反射(如 ...

  5. go语言nsq源码解读七 lookup_protocol_v1.go

    本篇将解读nsqlookup处理tcp请求的核心代码文件lookup_protocol_v1.go. 1234567891011121314151617181920212223242526272829 ...

  6. go语言nsq源码解读一-基本介绍

    简单介绍一下nsq. 参考 http://feilong.me/2013/05/nsq-realtime-message-processing-system 的介绍:NSQ是由知名短链接服务商bitl ...

  7. go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin

    nsqlookupd: 官方文档解释见:http://bitly.github.io/nsq/components/nsqlookupd.html 用官方话来讲是:nsqlookupd管理拓扑信息,客 ...

  8. go语言 nsq源码解读三 nsqlookupd源码nsqlookupd.go

    从本节开始,将逐步阅读nsq各模块的代码. 读一份代码,我的思路一般是: 1.了解用法,知道了怎么使用,对理解代码有宏观上有很大帮助. 2.了解各大模块的功能特点,同时再想想,如果让自己来实现这些模块 ...

  9. 网易2017校园招聘算法题c语言实现源码

    题目: 给定一个数组,除了一个数出现1次之外,其余数都出现3次.找出出现一次的数.如:{1, 2, 1, 2, 1, 2, 7}, 找出7. 格式: 第一行输入一个数n,代表数组的长度,接下来一行输入 ...

随机推荐

  1. learning java 文件锁

    import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; i ...

  2. ServiceStack.OrmLite 基本操作

    原文:https://www.cnblogs.com/wang2650/category/780821.html 原文:https://www.cnblogs.com/xxfcz/p/7045808. ...

  3. Web前端鼠标悬停实现显示与隐藏效果

    css定义,偏移量,相对定位,绝对定位 显示与隐藏 二维码相对于微信图标定位 鼠标悬停微信图标上显示 鼠标离开微信图标时隐藏 什么是定位,就是定义网页标签在运行时显示的位置 css提供Position ...

  4. vue 进入页面与离开页面触发事件

    1.切换进入当前路由之前的钩子函数 beforeRouteEnter <script> export default { beforeRouteEnter(to, form, next) ...

  5. Promise链式调用 终止或取消

    Promise回调分两种方法,then成功,catch失败 let promise = new Promise(function(resolve, reject){ resolve('第一次成功') ...

  6. jmeter接口自动化和性能学习目录

     目录黑色代表未完成的,绿色代表已完成的文章.目录的作用的为了引导和总结自己的学习,也是为了更好的分享给大家. 一.接口自动化 jmeter解决登录token获取 jmeter五种提取器 之 正则表达 ...

  7. NFV实验平台

    NFV架构如下图所示. NFVI对应于数据平面,数据平面转发数据并提供用于运行网络服务的资源. MANO对应于控制平面,该控制平面负责构建各种VNF之间的连接以及编排NFVI中的资源. VNF层对应于 ...

  8. pm升级到最新版本、指定版本

    npm 升级到最新版本 //linux下 npm install -g npm npm升级到指定版本 //比如升级到5.6.0 npm install -g npm@5.6.0

  9. 啃OBS源码-界面汉字

    插件对应该字体目录:D:\project\vs\obs\obsstudio21.12\build\rundir\Debug\data\obs-plugins obs对应该字体目录:D:\project ...

  10. 开启Nginx监控 with-http_stub_status_module

    1.开启监控with-http_stub_status_module ./configure  --with-openssl=/usr/local/ssl  --with-http_stub_stat ...