ceph RGW Multipart 上传文件过程

s3cmd put --multipart-chunk-size-mb=5 source/testfile s3://test-bucket/test

ceph RGW Multipart 上传文件过程_第1张图片

每生成一个 stripe 对象(StripeGenerator::create_begin、StripeGenerator::create_next),就会把这个 stripe 对象绑定到 RadosWriter 上,process 链的调用顺序是 HeadObjectProcessor::process
-> StripeProcessor::process
-> ChunkProcessor::process
-> RadosWriter::process

详细函数过程:

REST 请求的处理

process_request

init 用户,认证,权限,桶等参数

init 操作类型相关的初始化

检查权限

检查参数

返回头上加上操作的 bucket

execute

complete

返回 io 的完成状态

记录日志

RGWPutObj(向对象上传数据)

  • 获取 request 中的版本

  • 生成校验 md5 码

  • 检查配额

  • 为桶的 event_type 类型的 topic 预留用于 notification 的空间

  • 获取 dest_placement(name、storage class)(get_multipart_info)

  • 生成 processor

  • 包装加密 processor

  • 包装压缩 processor

  • 处理每个文件

    • 获取数据
      • 计算 hash
      • 更新 torrent
      • 处理机处理
    • 设置对象大小
    • 检查 aws4 验证与配额
    • 执行压缩
    • 检查 md5 校验
    • 设置 attr
      • acl
      • user manifest
      • slo manifest
      • etag
      • 上传 request 中的 attr
      • delete at
      • tags
      • 是否是 slo
      • legal hold
      • 生存时间 object retention
    • 完成 processor
  • 生成 torrent

  • 通知各 OSD 提交 (publish_commit)

AtomicObjectProcessor:

prepare
  • manifest 中记录 tail_ofs、stripe_max_size
  • 配置 bucket 与其 placement rule
  • manifest::gen 创建一个文件头 manifest (create_begin)
    • 绑定 0 号 obj 为当前 obj
    • 设置前缀 .xxxx_
    • 在前缀上加上 stripe 的位置
    • 设置对象大小
    • 设置object 的 key 在 tail_instance 上
    • 设置begin end 位置为 0
  • gen 生成一个 stripe_obj
  • 打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))

MultipartObjectProcessor

prepare
  • 设置前缀 obj_key.upload_id

  • 设置 stripe max size 与 part_num

  • manifest::gen 创建一个文件头 manifest (create_begin)

  • gen 生成一个 stripe_obj

  • stripe obj 转 obj

  • 设置其与前一版本的链接 index_hash_source

  • 打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))

  • 设置 obj 的大小(set_head_chunk_size)

complete
  • flush 没写完的数据
  • 获取实际写的大小,并更新统计到下一个 stripe 对象的位置
  • 设置 obj 禁用 versioning
  • 写元数据,把 prepare 时生成的 attrs 写进去 (_do_write_meta)
  • 生成这个 part 的信息 info,并序列化
  • 在 sys_obj 对象中存上 key 为 part.n,value 为序列化的 info 的映射
  • 清除临时 stripe 对象

AppendObjectProcessor

prepare
  • 检查对象是不是最后一个对象,只最后一个对象可追加

  • 设置 part_num 加1

  • 获取 etag

  • 获取 storage class

  • 获取前缀

  • 设置 stripe 大小与 part_num

  • manifest::gen 创建一个文件头 manifest (create_begin)

  • gen 生成一个 stripe_obj

  • 打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))

  • 设置 obj 的大小(set_head_chunk_size)

HeadObjectProcessor::process

  • 加密、压缩处理等

  • 处理第一个 part(process_first_chunk)

    • atomic:无操作
    • append:直接写数据
    • multipart:直接写数据,如果对象存在了,就生成新对象名(只是改前缀中的随机项),再重写
  • StripeProcessor.process

    • 每当一个 stripe 满了,就创建下一个 stripe (manifest_gen.create_next)
      • cur_stripe ++
      • 更新 obj 大小
      • 新 obj 名称为 cur_part_id + _ + cur_stripe
      • 更新 begin、end 的位置
    • gen 生成一个 stripe_obj
    • 打开相应 pool,set 这个 key(writer.set_stripe_obj(stripe_obj))
    • 生成这个 writer 的新 ChunkProcessor
  • ChunkProcessor.process

    • 积攒数据,每攒到一个 chunk 大小,就调用 writer 去写
    • 当没有数据时,当作是 flush 操作,也调用 writer 去写
  • RadosWriter.process

    • 生成写操作
    • 加入 pending 队列
    • 将结果存在 written 中

write_exclusive

  • 组装创建文件、写文件的操作 ObjectWriteOperation.create/write_full

  • 等待可写,将动作加入 pending 队列,并执行异步 operate(aio->get)

  • 耗尽 pending 写队列 aio->drain()

  • 将写后返回的对象加入 written 中

multipart 上传

RGWInitMultipart::execute

  • 获取请求中的参数
  • reserve 空间用于 notification
  • 生成upload_id 2~xxxx (2 指 v2 版本)
  • 生成 write 的操作
  • 将 upload_info (name和storage_class) 绑定到元数据中
  • 执行写元数据
  • 通知各节点提交

RGWCompleteMultipart::execute

删除原有的各part的object,并修改原 obj 的元数据。
最后删除原有的 .meta 文件

你可能感兴趣的:(ceph,ceph)