Ceph RGW 对象上传源码分析

本文深入分析了Ceph RGW对象上传的源码,包括整体上传和分段上传。RGWOp是操作的基础类,RGWPutObjProcessor_Atomic处理整体上传,RGWPutObjProcessor_Multipart处理分段上传。对象上传的关键步骤包括:prepare阶段初始化manifest,put_data_and_throttle阶段处理数据,handle_data阶段将数据切分并异步写入Rados,最后在complete阶段更新元数据和索引对象。整个过程确保了上传的兼容性和效率。
摘要由CSDN通过智能技术生成

RGW中OP请求处理函数的入口都是process_request,process_request会根据传入的RGWRados参数获取RGWOp,然后当请求合法性通过后去调用rgw_process_authenticated函数执行OP的具体动作。

请求的处理  Collapse source
int  process_request(RGWRados*  const  store,
                     RGWREST*  const  rest,
                     RGWRequest*  const  req,
                     const  std::string& frontend_prefix,
                     const  rgw_auth_registry_t& auth_registry,
                     RGWRestfulIO*  const  client_io,
                     OpsLogSocket*  const  olog)
{
     ...
     RGWOp* op = NULL;
     int  init_error = 0;
     bool  should_log =  false ;
     RGWRESTMgr *mgr;
     RGWHandler_REST *handler = rest->get_handler(store, s,
                                                auth_registry,
                                                frontend_prefix,
                                                client_io, &mgr, &init_error);
     ...
      op = handler->get_op(store); //解析出具体的OP
     ...
     ret = rgw_process_authenticated(handler, op, req, s); //验证OP
     if  (ret < 0) {
         abort_early(s, op, ret, handler);
         goto  done;
   }
rgw_process_authenticated函数内部执行OP具体动作时候,分为三个阶段pre_exec,execute和complete
OP执行  Collapse source
int  rgw_process_authenticated(RGWHandler_REST *  const  handler,
                               RGWOp *& op,
                               RGWRequest *  const  req,
                               req_state *  const  s,
                               const  bool  skip_retarget)
{
     ...
     req-> log (s,  "init op" );
   ret = op->init_processing();
   if  (ret < 0) {
     return  ret;
   }
   req-> log (s,  "verifying op mask" );
   ret = op->verify_op_mask();
   if  (ret < 0) {
     return  ret;
   }
   req-> log (s,  "verifying op permissions" );
   ret = op->verify_permission();
   if  (ret < 0) {
     if  (s->system_request) {
       dout(2) <<  "overriding permissions due to system operation"  << dendl;
     else  if  (s->auth.identity->is_admin_of(s->user->user_id)) {
       dout(2) <<  "overriding permissions due to admin operation"  << dendl;
     else  {
       return  ret;
     }
   }
   req-> log (s,  "verifying op params" );
   ret = op->verify_params();
   if  (ret < 0) {
     return  ret;
   }
   req-> log (s,  "pre-executing" );
   op->pre_exec();
   req-> log (s,  "executing" );
   op->execute();
   req-> log (s,  "completing" );
   op->complete();
     ...
}

所有的RGW 操作都是继承于基类RGWOp,然后具体的OP重写自己的的execute方法。

对象上传分为整体上传和分段上传。对于选择整体上传和分段上传的选择在于用户单次操作上传文件大小,若大于5GB对象就需要使用分段上传API,否则使用整体上传的API。这个就是用来兼容S3标准(对象操作

对于整体上传就会对应到RGWPutObjProcessor_Atomic处理类,分段上传会对应RGWPutObjProcessor_Multipart处理类。这两个类会对上传的对象做加密操作,压缩,数据处理等。是整个上传对象操作的核心处理类。关于对上传对象压缩处理见ceph 官方文档介绍

对于对象文件上传OP的类为RGWPutObj,其定义的execute函数为整个文件上传的入口,整个函数调用及嵌套关系如下所示:

RGWPutObj::execute
  • RGWPutObj_Compress::prepare
    • RGWPutObjProcessor_Atomic::prepare
  • put_data_and_throttle
    • RGWPutObj_Compress::handle_data
      • RGWPutObjProcessor_Atomic::handle_data
        • RGWPutObjProcessor_Atomic::write_data
          • RGWPutObjProcessor_Aio::handle_obj_data
            • RGWRados::aio_put_obj_data
              • librados aio API
    • RGWPutObjProcessor_Aio::throttle_data
  • RGWPutObjProcessor::complete
    • RGWPutObjProcessor_Atomic::complete

RGWPutObj::execute  Collapse source
void  RGWPutObj::execute()
{
  
   RGWPutObjProcessor *processor = NULL;
   // filter用于对数据进行处理,比如加密和压缩
   RGWPutObjDataProcessor *filter = nullptr;
   std::unique_ptr<RGWPutObjDataProcessor> encrypt;
   
   // 用于存储用户提供的md5、计算的md5 相关的数组
   char  supplied_md5_bin[CEPH_CRYPTO_MD5_DIGESTSIZE + 1];
   char  supplied_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
   char  calc_md5[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
   unsigned  char  m[CEPH_CRYPTO_MD5_DIGESTSIZE];
   MD5 hash;
 
   bufferlist bl, aclbl, bs;
   int  len;
   map<string, string>::iterator iter;
   bool  multipart;
   // copy source range 相关
   off_t fst;
   off_t lst;
   // 根据zone配置选择object的压缩类型,可为none或具体的压缩插件名字
   const  auto& compression_type = store->get_zone_params().get_compression_type(
       s->bucket_info.placement_rule);
   CompressorRef plugin;
   boost::optional<RGWPutObj_Compress> compressor;
 
   bool  need_calc_md5 = (dlo_manifest == NULL) && (slo_info == NULL);
   perfcounter->inc(l_rgw_put);
   op_ret = -EINVAL;
 
   //---------------------------------------------------------
   // 解析并检查请求参数是否完整、正确
   //---------------------------------------------------------
   
   // 判断用户请求object name、bucket name等是否正确
   if  (s->object.empty()) {
     goto  done;
   }
   if  (!s->bucket_exists) {
     op_ret = -ERR_NO_SUCH_BUCKET;
     return ;
   }
   // 解析并判断http请求的相关参数,包括copy obj的情况、包含tagging的情况、包含version的情况,以及基本的objname和bucketname解析
   op_ret = get_params();
   if  (op_ret < 0) {
     ldout(s->cct, 20) <<  "get_params() returned ret="  << op_ret << dendl;
     goto  done;
   }
 
   op_ret = get_system_versioning_params(s, &olh_epoch, &version_id); //版本号
   if  (op_ret < 0) {
     ldout(s->cct, 20) <<  "get_system_versioning_params() returned ret="
               << op_ret << dendl;
     goto  done;
  
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值