我们暴露三个基本协议给Github终端用户: HTTP, SSH, 和 Git。 当你用你喜欢的浏览器浏览网站时, 你正在使用HTTP. 当你clone, pull, 或者 push 到一个私有 URL 时,比如git@github.com:mojombo/jekyll.git ,你正在通过SSH来实现这些。 当你从一个公开的仓库通过一个URL比如 git://github.com/mojombo/jekyll.git 来 clone 或者 pull 的时候,你正在使用 Git 协议。
理解它的构架最简单的方法是通过跟踪每一个请求是如何通过系统传送的。
在这个例子中我会向你展示一个页面树的请求,例如http://github.com/mojombo/jekyll,是如何发生的。
当你从网络访问我们的服务,请求首先到达的是负载均衡服务器。对于负载均衡我们使用一对跑着ldirectord的 Xen 虚拟机实例,我们称之为 lb1a,lb1b。在任意时刻,其中主实例保持激活状态,当主实例故障从实例随时接替主实例的工作.负载均衡器不仅可以根据IP和端口号将请求定向到各种服务器,必要的时候还可以从负载均衡池中删除操作异常的服务器.当对指定的池没有对应的服务器在工作,则定向到一个简单的静态网站,而不是拒绝链接。
对主网站的访问将被负载均衡器分发到四个前端服务器.这四个服务器每个都是8核 16G内存的物理主机,命名为 fe1 ... fe4。Nginx 接受到请求链接后发送给 16 个进程的 Unicorn 守护进程.其中的一个进程获取请求后执行相应的 Rails 代码处理这个请求。
许多页面需要查询数据库.我们的MySQL数据库运行在一个双八核处理器、32GB内存和15k RPM SAS硬盘的服务器上.它们的名字分别是da1a和db1b.在任意特定的时间内,其中的一个硬盘将作为主盘而另一个将作为从盘.MySQL的逻辑复制是通过DRBD(Distributed Replicated Block Device)完成的.
如果页面请求的信息是一个Git 仓库同时这些数据又没有被缓存,那么它就会用到Grit library去重新请求这些信息.为了适应Rackspace的环境,我们还改写了Grit从而实现一些新功能.我们尝试配对每一个需要登陆Grit::Git项目文件系统的请求,当我们把Grit::Git作为存根时就可以让RPC calls(远程过程调用)更配合Smoke服务.Smoke服务可以让磁盘访问这些存放,从而根本上把显示Grit::Git作为服务.它被叫做Smoke只是因为Grit是运行在云端的,懂了吗?
被存放的 Grit 发起 RPC 请求到 smoke ,smoke 是一个负载均衡映射到前端服务器的主机名。每一个前端服务器运行四个 HAProxy 之下的 ProxyMachine 实例,这个实例是 Smoke 服务请求的代理。ProxyMachine 是可编写 Ruby 逻辑代码的内容意识 TCP 路由代理。这个代理检查请求并获取指定仓库的用户名。我们使用一个叫做 Chimney 的专有库去为用户路由。一个用户的路由是用户的仓库存放所在的文件服务器的主机名。
Chimney 通过访问 Redis 查找路由。Redis 运行在数据库服务器中。我们使用 Redis 的键值存储来保存路由信息和数据的变化。
一旦 Smoke 代理判断好了用户的路由,它就建立一个透明的代理到对应的文件服务器上.我们有四对分别为8核 16G,六个 300G 15K RPM 的磁盘做 RAID 10 的文件服务器,命名为:fs1a,fs1b....fs4a,fs4b。每一对服务器有一台主服务器一台备用服务器,任何时间当主服务器出现问题备用服务器可以接替它的工作。通过使用DRBD,所有的仓库数据实时地从主服务器同步到备用服务器中。
每个文件服务器运行着两个 Ernie RPC 服务,每个 Ernie 产生 15 个 Ruby 进程。这些进程将发起 RPC 重新建立 Grit 请求。Grit 的响应将由 Smoke 代理被发送回 Rails 程序中。
对于我们的数据序列化以及 RPC 协议,我们使用的是 BERT 和 BERT-RPC。你可能没听说过他们,因为他们是新研发的。我研发这个两个产品是因为我评估过的相关产品找不到满意的选择,并且我想去实际思考了一段时间的想法.在你对此感到崩溃之前,不妨读读我的文章: Introducing BERTand BERT-RPC ,这是关于这些技术怎么来的,以及我打算怎么去实现。
如果你只是打算看一下说明,请访问:http://bert-rpc.org。
如果对代码感兴趣,可以查看我的 Ruby BERT 序列化库 BERT,我的 Ruby BERT-RPC 客户端 BERTRPC, 以及我的 Erlang/Ruby 混合 BERT-RPC 服务程序 Ernie.。这些都是GitHub代码托管仓库使用的库。
如果你运行一个命令:git clone tom@frost:mojombo/bert,在这个场景下,Git 所做的是,用 SSH 方式链接到 frost 主机,认证 tom 用户,以及在远程执行 git upload-pack mojombo/bert。现在你的客户端就可以用SSH的方式读写访问远程Git服务了。很便捷是吧。
当然,允许任意地执行命令是不安全的,所以 SSH 包含了限制什么命令可以执行的能力。一个非常简单的例子,你可以限制执行命令到Git所包含的 git-shell。所有这些脚本将检查确保你尝试执行的命令是以下之一:git upload-paack, git receive-pack , git upload-archive 。如果是以上之一,可以使用exec 来使新的进程代替当前进程。就犹如你直接执行了这个命令。
评论删除后,数据将无法恢复
评论(4)
引用来自“红薯”的评论
@oscfox 这篇文章必看,咱们翻译一下吧引用来自“红薯”的评论
@oscfox 这篇文章必看,咱们翻译一下吧