延续上篇,继续往下看
写在前面
松鼠哥的ceph专业课程上线啦!
面向新手同学,从0实战,全面入门ceph安装部署与运维,有需要的同学赶紧扫码订购吧:
继续使用s3cmd进行对象存储流程的探究
分片的情况
同样,使用s3cmd上传一个31MB的文件,由于超过了s3cmd默认的15M/块。因此会产生3个分片
1 | [store@server227 build]$ s3cmd put sample.txt s3://cpp-bucket1/multipart.file |
接下来解读日志,由于进行了分片,日志内容较多,其中很多内容与不分片是相同的,所以这里只关注其中的不同点
这里先介绍分片上传的过程,与不分片上传只产生单个PUT的HTTP请求不同,分片上传的HTTP请求要多几个,因为客户端在上传前,需要告知服务器,它要分片上传,并且在分片全部传完后,也要告诉服务器,分片全部传完了,所以这里会看到在上传前后,有两个POST
的HTTP请求
首先是第一个HTTP请求
1 | 2019-05-31 17:26:54.023 7fdc91735700 20 CONTENT_LENGTH=0 |
注意到这三个参数,首先上传的CONTENT_LENGTH=0
,因为POST
不带任何的对象数据,然后是HTTP类型为POST,最后URI是目标obj
接下来
1 | 2019-05-31 17:26:54.023 7fdc91735700 10 op=28RGWInitMultipart_ObjStore_S3 |
这个op的字段变成了28RGWInitMultipart_ObjStore_S3
,就是为了告诉服务器,要进行分片上传,让服务器做好准备
1 | 2019-05-31 17:26:54.035 7fdc91735700 2 req 8:0.0119997s:s3:POST /cpp-bucket1/multipart.file:init_multipart:executing |
与不分片上传不同的是,这里的流程走的是init_multipart
,并且,没有数据上传,仅是创建了一个用作分片标识的对象cpp-bucket1:_multipart_multipart.file.2~JrnG-RZNXNn0fbawnAntHpPjhIzZwdi.meta
,后续上传分片时,handler就能够知道哪些分片是同一个对象的
有了第一个POST的铺垫,接下来客户端开始上传分片
1 | 2019-05-31 17:26:54.121 7fdc91735700 20 CONTENT_LENGTH=15728640 |
分片的HTTP头部字段与不分片的差别在于QUERY_STRING
,其包含了分片的重要信息,另外注意CONTENT_LENGTH
为15M
1 | 2019-05-31 17:26:54.127 7fdc91735700 20 Read xattr: user.rgw.acl |
这里有读取元数据信息的操作,因为分片上传是有一定的限制的,例如限制一个对象的分片数量,默认是不限制,但是它也要检查了才能确认
1 | 2019-05-31 17:26:54.269 7fdc91735700 1 -- 192.168.115.227:0/3536016146 --> 192.168.115.227:6805/1505287 -- osd_op(unknown.0.0:62833 7.0 7:1e43fb08:::ba85d906-5451-49e4-b0e1-f90b7db13259.4155.1__shadow_multipart.file.2~JrnG-RZNXNn0fbawnAntHpPjhIzZwdi.1_2:head [writefull 0~4194304] snapc 0=[] ondisk+write+known_if_redirected e30) v8 -- 0x5619de63d8c0 con 0 |
针对这两个op,在此前我们设置max chunk为8M,因此s3cmd上传一次,就产生15M的数据,超过了8M,因此rgw会去读取2次缓冲区,每一次读取,得到的数据都超过了4M,因此会产生2个osd op,每次下发4M到osd
仔细看这2个osd op,有什么特点呢,嗯,就是名字有特点,含有__shadow_
表示它是某个对象的部分数据块,而含有multipart
显然表示它是一个分片,后面的~JrnG-RZNXNn0fbawnAntHpPjhIzZwdi
是不是有点眼熟呢,这个标识是在第一个HTTP请求中创建的,obj=cpp-bucket1:_multipart_multipart.file.2~JrnG-RZNXNn0fbawnAntHpPjhIzZwdi.meta
,这样就唯一标识了这组分片,然后以分片编号收尾,这就是分片的组织形式
中间的几个HTTP上传请求大同小异,接下来看一下最后一个HTTP请求的日志
1 | 2019-05-31 17:26:54.605 7fdc91735700 20 CONTENT_LENGTH=303 |
与第一个请求一样,使用了POST方法,接下来
1 | 2019-05-31 17:26:54.606 7fdc91735700 10 op=32RGWCompleteMultipart_ObjStore_S3 |
op字段明确表示了这个请求是要完成分片上传,继续往下看
1 | 2019-05-31 17:26:54.606 7fdc91735700 2 req 12:0.000999971s:s3:POST /cpp-bucket1/multipart.file:complete_multipart:verifying op params |
注意到,这些处理函数与此前的都不同,说明分片上传时候,使用的流程是有一套的,最后完成分片的上传工作
1 | 2019-05-31 17:26:54.640 7fdc91735700 2 req 12:0.034999s:s3:POST /cpp-bucket1/multipart.file:complete_multipart:completing |
至此,整个分片上传的过程就搞清楚了
总结
从日志看来,rgw的数据上传包含一下两部分
单片上传
单片上传的片大小取决于客户端,实验中使用s3cmd测试,默认是15M一个片,在实际使用场景中,我们可以根据要求进行定制这个值
单片上传仅发出一个HTTP PUT请求,服务器则在进行必要的鉴权后,接受全部数据,下发到osd,最后更新相关元数据信息,返回处理结果
分片上传
分片上传对比单片上传有必要的两个POST操作,在上传前需要通知服务器,客户端准备使用分片上传,而在全部分片传完后,也要通知服务器分片已经传完,服务器对分片的组织也可以通过日志很清晰地看出来,相同的一组分片带有相同的随机标识
RGW处理逻辑从代码的角度看还是比较清晰的,本篇分析基于日志,结合部分代码,总的来说比较粗糙,应对一般的故障处理已经足够了,如果说要深究每一个过程中的函数,那么要花费的精力也是很多的,从调优的角度来说,上传数据的三大阶段中,第二阶段花费了绝大部分的时间,因此这部份需要重点梳理
- 本文作者: 奋斗的松鼠
- 本文链接: http://www.strugglesquirrel.com/2019/07/07/看懂ceph日志系列之rgw上传op处理流程-下/
- 版权声明: 本博客所有文章除特别声明外,创作版权均为作者个人所有,未经允许禁止转载!