作者简介
王振威,CODING创始团队成员之一,多年系统软件开发经验,擅长Linux,Golang,Java,Ruby,Docker等技术领域,近两年来一直在CODING从事系统架构和运维工作
前言
最近Google发布了一篇文章,描述了对Git的一个传输协议的更新,引起了国内技术圈的不小规模的轰动(相关文章请自行百度“Git v2性能提升”)。 很多技术圈的朋友也在转载这个新闻,那至于性能改进有多大,里面的细节是什么呢?事实上这次改动只在极端情况下有性能提升,绝大多数情况下,用户感受不到性能的提升。很多不明所以的转发大概是因为Google的品牌效应吧 :)
Git是什么?
为了讲清楚why,我们先来简单介绍一下Git相关的协议。如果你还不了解Git,想了解更多内容,可参考其官方网站:http://git-scm.com/ .也可来https://coding.net/help/doc/git这里了解如何在国内使用优质快速的Git托管服务。
Git传输协议
Git常见的有三种协议,SSH,HTTP(S),Git,使用最广泛的是前两种。
让我们来看一下,HTTP(S)和SSH协议的使用示例
git clone https://git.coding.net/wzw/coding-demo.git
Cloning into 'coding-demo'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
Cloning into 'coding-demo'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.
可以看到,对于全新clone来讲两者基本上的过程是一模一样的。
事实上,Git底层对于各种应用层协议的底层处理是一致的,不管是HTTP(S)还是SSH还是Git协议。
让我们来进一步看一下,Git在传输过程中都做了什么。
GIT_TRACE=1 GIT_TRACE_PACKET=1 git clone https://git.coding.net/wzw/coding-demo.git
17:48:21.767799 git.c:344 trace: built-in: git 'clone' 'https://git.coding.net/wzw/coding-demo.git'
Cloning into 'coding-demo'...
17:48:21.797959 run-command.c:626 trace: run_command: 'git-remote-https' 'origin' 'https://git.coding.net/wzw/coding-demo.git'
17:48:22.278880 pkt-line.c:80 packet: git
17:48:22.279390 pkt-line.c:80 packet: git
17:48:22.279405 pkt-line.c:80 packet: git
17:48:22.279419 pkt-line.c:80 packet: git
17:48:22.279431 pkt-line.c:80 packet:
好,基础知识补充完毕,有没有发现火爆的区块链在技术层面上跟Git的存储是有相似之处的 :)
在Clone过程中,服务器端首先会推荐给客户端一些ref列表,这也是Git v2协议号称的性能改进的地方,后文有解释。
像这样:
17:49:19.772436 pkt-line.c:80 packet: clone
17:49:19.772566 pkt-line.c:80 packet: clone
很显然,上文中的40位16进制数字就是对应后面的ref指向的对象ID。
而客户端,只需要依据自己感兴趣的ref和自己本地已经存在的对象库(对于pull和fetch来讲,本地有对象库,对于clone来讲本地还没有对象库,那么他就是需要所有的感兴趣的对象)。
在客户端计算完毕自己感兴趣的对象列表后,会用want指令告诉远端服务器。
17:49:19.776185 pkt-line.c:80 packet: clone> want fdacba1d541c75bd48f2cd742ee18f77ea3517a1 multi_ack_detailed side-band-64k thin-pack ofs-delta deepen-since deepen-not agent=git/2.15.1.(Apple.Git-101)
17:49:19.776215 pkt-line.c:80 packet: clone> want fdacba1d541c75bd48f2cd742ee18f77ea3517a1
17:49:19.776239 pkt-line.c:80 packet: clone> want 30eb4b0d813c662c4d7e87c4d3b4cf561e544f8e
如果客户端执行的是pull或者fetch,他还会告诉远端自己已经有了什么对象(在文章的后面,我们会补充一段专门说明此点)。
远端服务器会根据客户端想要的对象以及客户端已经有的对象并对比自身的对象库和对象依赖关系,将客户端必须的对象整理起来并打包压缩传给客户端。
客户端收到对象包后,解包并校验对象,并更新引用的对应指向。
Google在Protocol version 2做了什么
完整的version 2的协议说明在这里:https://www.kernel.org/pub/software/scm/git/docs/technical/protocol-v2.html
这里我们对其做的主要改动做些说明,主要有三点:
服务端引用过滤
新特性的易扩展性升级(例如可声明想要什么ref)
简化的客户端HTTP协议处理
被很多标题党夸大其词的主要是其第一点:服务端引用过滤。
Google官方的博客中对此段的描述是这样的:
The main motivation for the new protocol was to enable server sid
领取专属 10元无门槛券
私享最新 技术干货