Administrator
发布于 2023-03-20 / 7 阅读
0
0

rgw_请求处理流程

rgw\_请求处理流程

前言

本文主题: 当我们用 s3cmd(s3,Swift等)上传文件时候,rgw是如何处理的(这次先单独讨论 整体上传

从一个s3请求 到如何转换成 rgwRequest 再到 数据如何切割存储到rados中

!image-20230207101046899

整体架构

!image-20230320205947939

接受请求的 前端– beast 接受请求的 前端– beast

!image-20230321165532366

在N版中默认 是用 beast (可以异步处理http服务器 )前端来解析HTTP请求,rgw 默认是使用beast,并用 RGWAsioFrontend 类封装,其关系如下图所示

RGWAsioFrontend 类关系 RGWAsioFrontend 类关系

!image-20230320210937471

front 启动流程图

!image-20230320211404663

关键流程


int AsioFrontend::init()
{
  boost::system::error_code ec;
// ......
  bool socket_bound = false;
  // start listeners
  for (auto& l : listeners) {
// ......
    l.acceptor.listen(max_connection_backlog);
    l.acceptor.async_accept(l.socket,
                            [this, &l] (boost::system::error_code ec) {
                              accept(l, ec);
                            });
  }
//............
}


void AsioFrontend::accept(Listener& l, boost::system::error_code ec)
{
 //..............
  l.acceptor.async_accept(l.socket,
                          [this, &l] (boost::system::error_code ec) {
                            accept(l, ec);
                          });
  // spawn a coroutine to handle the connection
 //..............
#else
  {
#endif // WITH_RADOSGW_BEAST_OPENSSL
    boost::asio::spawn(context,
      [this, s=std::move(socket)] (boost::asio::yield_context yield) mutable {
        Connection conn{s};
        auto c = connections.add(conn);
        auto buffer = std::make_unique<parse_buffer>();
        boost::system::error_code ec;
        handle_connection(context, env, s, *buffer, false, pause_mutex,
                          scheduler.get(), ec, yield);
        s.shutdown(tcp::socket::shutdown_both, ec);
      });
  }
}

http 请求时如转换的 OP的

处理流程

!image-20230321171225013

Restful -> Handle -> OP Restful -> Handle -> OP

Restul 的注册


rgw_main.cc

int mian(){

.....
RGWREST rest;

list<string> apis;
get_str_list(g_conf()->rgw_enable_apis, apis);
map<string, bool> apis_map;
for (list<string>::iterator li = apis.begin(); li != apis.end(); ++li) {
    apis_map[*li] = true;
}

if (apis_map.count("s3") > 0 || s3website_enabled) {
    if (! swift_at_root) {
      rest.register_default_mgr(set_logging(rest_filter(store, RGW_REST_S3,
                                 new RGWRESTMgr_S3(s3website_enabled, sts_enabled, iam_enabled, 							  pubsub_enabled))));
    } else {
      return EINVAL;
    }
  }
}
......
.....
}

Handle 生成 Handle 生成

!image-20230321112648600 相关类图


//根据不同的Restfull
rgw_process.cc
process_request()
-->RGWHandler_REST *handler = rest->get_handler(store, s);
-->RGWHandler_REST* RGWRESTMgr_S3::get_handler(struct req_state* const s,
                                            const rgw::auth::StrategyRegistry& auth_registry,
                                         const std::string& frontend_prefix)
{  RGWHandler_REST* handler;
  // TODO: Make this more readable
  if (is_s3website) {
    if (s->init_state.url_bucket.empty()) {
      handler = new RGWHandler_REST_Service_S3Website(auth_registry);
    } else if (s->object.empty()) {
      handler = new RGWHandler_REST_Bucket_S3Website(auth_registry);
    } else {
      handler = new RGWHandler_REST_Obj_S3Website(auth_registry);
    }
  } else {
    if (s->init_state.url_bucket.empty()) {
      handler = new RGWHandler_REST_Service_S3(auth_registry, enable_sts, enable_iam, enable_pubsub);
    } else if (s->object.empty()) {
      handler = new RGWHandler_REST_Bucket_S3(auth_registry, enable_pubsub);
    } else {
      handler = new RGWHandler_REST_Obj_S3(auth_registry);
    }
  }

  return handler;
}

OP生成

!image-20230321172112249


rgw_process.cc
process_request()
 -->RGWOp* op = nullptr;
    op = handler->get_op(store);
    RGWOp* RGWHandler_REST::get_op(RGWRados* store)
    {
      RGWOp *op;
      switch (s->op) {
    ....
       case OP_PUT:
         op = op_put();   // RGWHandler_REST_Obj_S3::op_put()
         break;
    .....
       default:
         return NULL;
      }
      if (op) {
        op->init(store, s, this);
      }
      return op;
    } /* get_op */

RGWOp *RGWHandler_REST_Obj_S3::op_put()
{
  if (is_acl_op()) {
    return new RGWPutACLs_ObjStore_S3;
  } else if (is_tagging_op()) {
    return new RGWPutObjTags_ObjStore_S3;
  } else if (is_obj_retention_op()) {
    return new RGWPutObjRetention_ObjStore_S3;
  } else if (is_obj_legal_hold_op()) {
    return new RGWPutObjLegalHold_ObjStore_S3;
  }

  if (s->init_state.src_bucket.empty())
    return new RGWPutObj_ObjStore_S3;
  else
    return new ;
}

总结: 三者的联系(以 put obj 为例)

!三者的关系图

OP的执行

!image-20230321162452914

请求的验证

  • verify\_requester -> RGWHandler\_REST\_S3::authorize

根据不同 API类型来进行请求的权限验证,支持 STS 和 keystone 认证 !image-20230321174107274

  • postauth\_init -> RGWHandler\_REST\_S3::postauth\_init()

验证 Bucket 和 Object· 命名是否合法

  • rgw\_process\_authenticated

-   **RGWHandler_REST::init_permissions    -> 	do_init_permissions()**

    进行权限初始化   从持久化数据中获取ACL

    ![image-20230321175841030](http://img.rui.vin/202303211758094.png)

-   RGWHandler_REST::read_permissions :

    	根据不同的OP来获取RGWOp的操作权限

-   **RGWOp::init_processing -> RGWOp::init_quota()**

    -   获取Bucket的quota

    -    获取User的quota

    

-   RGWOp::verify_op_mask:
    -   **通过位运算的方式来判断当前操作是否在支持的操作列表中**
    -   ![image-20230321200323145](http://img.rui.vin/202303212003220.png)

-   RGWPutObj::verify_permission

    验证ACL 是否匹配

-   RGWOp::verify_params

    对put 来说是 验证Obj的大小是否超过限制


/third-bucket/15M
content-length:15728640
content-type:application/octet-stream
host:10.1.31.40:18021
x-amz-content-sha256:167b76d3a8d20df15c421d48877c330597f6309d6b55c7b5327df5d89a51423f
x-amz-date:20230320T040318Z
x-amz-meta-s3cmd-attrs:atime:1679131627/ctime:1679131611/gid:0/gname:root/md5:14b17234e237505421b6492b8d757507/mode:33188/mtime:1679131611/uid:0/uname:root
x-amz-storage-class:STANDARD


评论