看多了 Go 源代码,看一看应用,尤为是比较短小且有趣的应用代码,感受颇有意思,并且举重若轻。nginx
若是顺带修一下小的错误,成为 Contributor,那就更多了一种成就感。就像杨文前几天成为 Go Contributor 那样,从小处开始,慢慢提高技术含量,总有一天,慢慢成为真正的 Contributor,像曹大那样。git
某天欧神和杨文不知道怎么鼓捣出了一个 golang.design 网站,前一阵子欧神又发布了一个 redir 项目。它实际上是一个跳转,好比,欧神分享的 Gophercon 2020 的 PPT 连接:golang.design/s/gophercon… dropbox 的一个文件分享页面。可是用 “/s/gophercon2020” 就会显得很是的优雅和高级。相似的,还有一些欧神作的分享,如 golang.design/s/go2generi… 等,都会经过 /s/
跳转到实际的地址去。至于为何是 /s/
路径,其实这个项目最初的名字是 short,也就是短网址的意思。github
因此,我今天要介绍的就是 redir 的实现原理以及部署。golang
首先来看一下 redir 的两个核心功能:短网址跳转(/s);处理 go get
请求(/x)。前者很好理解,我访问短网址 golang.design/s/go2generi… 给我重定向到真实的 google slice 的地址;后者则不那么好理解,它处理的是咱们在项目中 import 了一个 golang.design 下面的某个包,例如:import "golang.design/x/verbose"
,那么 go get
来获取这个包的时候会去 github 上 golang.design 相应目录下找,但这一切并非天然发生的,须要经过返回的 header
告知 go get
一些信息。redis
对于比较知名的,如 github,我这样写:import github.com/go-redis/redis/v8
,go get
就知道去 github 官网去找,可是对于 golang.design 的库那就不知道怎么找了,因此它会尝试访问 https://golang.design/x/pkg/foo?go-get=1
来获取相关信息,因而 /x
handler 就在 header 里返回 meta 信息,告诉 go get
去 github 找。docker
当 go get 收到上图的 HTTP 响应,会根据第一个红框的提示去 github.com/golang-desi… 这里找对应的包;而若是是浏览器过来的请求,则会重定向到 pkg.go.dev 查看包的详细信息。前者实际就是和 go get 交互的协议,具体的能够在这里看到。浏览器
有了短网址跳转,天然就想知道访问每一个短网址的 uv/pv 状况,若是访问路径 /s
后不接任何字符,那就返回短网址的汇总信息:markdown
了解清楚了功能,咱们来看看如何用代码实现。架构
main
函数会首先会根据传入的命令行参数 *daemon 来决定是开启一个 server,仍是执行增长 alias(短连接和长连接对)、更新 alias 的命令。前者持续运行,后者则只执行一次,程序就会结束。app
若是是启动一个 server,会首先链接 redis,初始化一个本地的 cache,用于加快响应速度;同时会启动两个异步协程:counting 和 backup,前者用于计数 uv/pv,后者则用于备份 redis 中的数据。
接着会注册 /.info
、/s
、/x
三个 handler,/.info
用来看一下程序相关的版本信息(内部会经过 nginx 屏蔽,外部没法访问);/s
用来处理短连接;/x
则用于执行包相关的请求。
/s
的处理逻辑是先从本地 cache 拿和短链相对应的实际连接,若是没有拿到,则从 redis 拿,最后调用 http.Redirect(w, r, url, http.StatusTemporaryRedirect)
重定向到实际连接地址。
最后,启动一个异步协程把访问信息(ip)添加到一个 channel 中去,用于计算 pv/uv。
关于 /s
handler 还有一类特殊的请求,即短连接为空,直接访问 https://golang.design/s/
,那就会返回全部的短连接而且展现相应的 uv/pv 信息。
完成上述这些,最后开始监听端口,处理请求。
另一个流程就是根据命令行参数执行 alias 的增删改查,是一次性的行为。
总体的架构图:
最后咱们来看下如何部署到本身的云主机上,我会修改为本身的域名:qcrao.com。固然,redir 还会向 Google Analytics 发送追踪数据,须要将 id 改为本身的。
首先要安装 docker 和 docker-compose,这个就不细说,对着命令敲就行了。
而后编译 redir.app:
make all
复制代码
启动 redir 和 redis 容器:
make up
复制代码
添加一个新的 alias:
./redir.app -a ck-s -l https://changkun.de/s/
复制代码
整体来看,项目的逻辑是比较简单清晰的,但涉及到东西其实也很多,麻雀虽小,五脏俱全。从实现到部署到运维,都须要了解。若是把整个都走通了,仍是颇有收获的。
在“玩弄” redir 的过程当中,修了一下 Makefile 文件,增长了一个 stats 页面的排序,也所以成为 redir 的从 Contributor,nice!