看多了 Go 源代码,看一看应用,尤其是比较短小且有趣的应用代码,感觉很有意思,而且举重若轻。

如果顺带修一下小的错误,成为 Contributor,那就更多了一种成就感。就像杨文前几天成为 Go Contributor 那样,从小处开始,慢慢提升技术含量,总有一天,慢慢成为真正的 Contributor,像曹大那样

某天欧神和杨文不知道怎么鼓捣出了一个 golang.design 网站,前一阵子欧神又发布了一个 redir 项目。它其实是一个跳转,比如,欧神分享的 Gophercon 2020 的 PPT 链接:https://golang.design/s/gophercon2020,其实最后会跳转到一个 dropbox 的一个文件分享页面。但是用 “/s/gophercon2020” 就会显得非常的优雅和高级。类似的,还有一些欧神做的分享,如 https://golang.design/s/go2generics 等,都会通过 /s/ 跳转到实际的地址去。至于为什么是 /s/ 路径,其实这个项目最初的名字是 short,也就是短网址的意思。

所以,我今天要介绍的就是 redir 的实现原理以及部署。

首先来看一下 redir 的两个核心功能:短网址跳转(/s);处理 go get 请求(/x)。前者很好理解,我访问短网址 https://golang.design/s/go2generics,redir 给我重定向到真实的 google slice 的地址;后者则不那么好理解,它处理的是我们在项目中 import 了一个 golang.design 下面的某个包,例如:import "golang.design/x/verbose" ,那么 go get 来获取这个包的时候会去 github 上 golang.design 相应目录下找,但这一切并不是自然发生的,需要通过返回的 header 告知 go get 一些信息。

对于比较知名的,如 github,我这样写:import github.com/go-redis/redis/v8go get 就知道去 github 官网去找,但是对于 golang.design 的库那就不知道怎么找了,所以它会尝试访问 https://golang.design/x/pkg/foo?go-get=1 来获取相关信息,于是 /x handler 就在 header 里返回 meta 信息,告诉 go get 去 github 找。

与 go get 交互

当 go get 收到上图的 HTTP 响应,会根据第一个红框的提示去 https://github.com/golang-design/verbose 这里找对应的包;而如果是浏览器过来的请求,则会重定向到 pkg.go.dev 查看包的详细信息。前者实际就是和 go get 交互的协议,具体的可以在这里看到。

有了短网址跳转,自然就想知道访问每个短网址的 uv/pv 情况,如果访问路径 /s 后不接任何字符,那就返回短网址的汇总信息:

uv/pv

了解清楚了功能,我们来看看如何用代码实现。

main 函数会首先会根据传入的命令行参数 *daemon 来决定是开启一个 server,还是执行增加 alias(短链接和长链接对)、更新 alias 的命令。前者持续运行,后者则只执行一次,程序就会结束。

如果是启动一个 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/

访问 https://www.qcrao.com/s/,大功告成:

qcrao.com/s/

总体来看,项目的逻辑是比较简单清晰的,但涉及到东西其实也不少,麻雀虽小,五脏俱全。从实现到部署到运维,都需要了解。如果把整个都走通了,还是很有收获的。

在“玩弄” redir 的过程中,修了一下 Makefile 文件,增加了一个 stats 页面的排序,也因此成为 redir 的从 Contributor,nice!