中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么理解RGW中request的處理流程

發布時間:2021-12-30 16:40:34 來源:億速云 閱讀:161 作者:iii 欄目:云計算

這篇文章主要介紹“怎么理解RGW中request的處理流程”,在日常操作中,相信很多人在怎么理解RGW中request的處理流程問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么理解RGW中request的處理流程”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

源碼解讀RGW中request的處理流程

請求處理流程圖

以civetweb為例

怎么理解RGW中request的處理流程

  1. rgw_main.cc為整個radosgw服務的入口,main()函數中根據在ceph.conf的rgw frontends參數設置來選擇不同的前端類型,之后執行相應的run()方法實現整個frontend服務的啟動。注意這里會根據ceph.conf中rgw_enable_apis的設置,實現s3、swift、admin等多種類型的接口生成不同的handler,具體代碼如下

    #src/rgw/rgw_main.cc
    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(new RGWRESTMgr_S3(s3website_enabled))); #設置S3接口默認handler為RGWRESTMgr_S3
    ...
      if (apis_map.count("swift") > 0) {
        do_swift = true;
        swift_init(g_ceph_context);
    
        RGWRESTMgr_SWIFT* const swift_resource = new RGWRESTMgr_SWIFT;#設置swift接口默認handler為RGWRESTMgr_SWIFT
        ...


  2. 之后在對應的rgw_civetweb_fronted.cc中,根據之前介紹的civetweb啟動流程,設置相應啟動參數,之后使用mg_start()完成civetweb的啟動。(注意參數中callback設置的是civetweb_callback)

    #src/rgw/rgw_civetweb_frontend.cc
    int RGWMongooseFrontend::run() {
      char thread_pool_buf[32];
      snprintf(thread_pool_buf, sizeof(thread_pool_buf), "%d",
    	   (int)g_conf->rgw_thread_pool_size);
      string port_str;
      map<string, string> conf_map = conf->get_config_map();
      conf->get_val("port", "80", &port_str);
      conf_map.erase("port");
      std::replace(port_str.begin(), port_str.end(), '+', ',');
      conf_map["listening_ports"] = port_str; #civetweb默認啟動監聽端口
      set_conf_default(conf_map, "enable_keep_alive", "yes"); #keep_alive參數設置
    
      set_conf_default(conf_map, "num_threads", thread_pool_buf); #默認threads設置
      set_conf_default(conf_map, "decode_url", "no");
      ...
      struct mg_callbacks cb;
      memset((void *)&cb, 0, sizeof(cb));
      cb.begin_request = civetweb_callback; #回調函數設置
      cb.log_message = rgw_civetweb_log_callback;
      cb.log_access = rgw_civetweb_log_access_callback;
      ctx = mg_start(&cb, &env, (const char **)&options); #啟動服務
    
      if (!ctx) {
        return -EIO;
      }
    
      return 0;
    } /* RGWMongooseFrontend::run */


  3. 經過上一步的設置,在civetweb_callback中每一個request請求都需要經過process_request()進行處理,注意每個request請求都會綁定一組RGWRados(負責底層Librados的數據讀寫)/RGWREST(對應request和Response的處理)/OpsLogSocket(日志消息記錄)

    #src/rgw/rgw_civetweb_frontend.cc


static int civetweb_callback(struct mg_connection* conn) { struct mg_request_info* req_info = mg_get_request_info(conn); RGWMongooseEnv* pe = static_cast<RGWMongooseEnv *>(req_info->user_data);

{ // hold a read lock over access to pe->store for reconfiguration RWLock::RLocker lock(pe->mutex);

RGWRados* store = pe->store; RGWREST* rest = pe->rest; OpsLogSocket* olog = pe->olog;

RGWRequest req(store->get_new_req_id()); RGWMongoose client_io(conn);

int ret = process_request(pe->store, rest, &req, &client_io, olog); #每個request請求綁定一組前面的RGWRados、RGWREST、OpsLogSocket ... ```

  1. 之后調用rgw_process.cc中的process_request(),其中rest->get_handler根據請求的URL是否包含bucket、object信息,獲取到對應的handler類型,之后調用handler->get_op(store)根據前面取得的handler對應request_method獲取到最終的handler,之后觸發handler對應的pre_exec()、execute()、complete()完整整個request請求的處理,代碼如下:

    #src/rgw/rgw_process.cc
    int process_request(RGWRados* store, RGWREST* rest, RGWRequest* req,GWStreamIO* client_io, OpsLogSocket* olog)
    {int ret = 0;
    client_io->init(g_ceph_context);
    ...
    RGWHandler_REST *handler = rest->get_handler(store, s, client_io, &mgr,&init_error); #這里根據URL里面是否包含bucket、Object字段會進一步獲取到對應的handler類型
    if (init_error != 0) {
    abort_early(s, NULL, init_error, NULL);
    goto done;
    }
    dout(10) << "handler=" << typeid(*handler).name() << dendl;
    should_log = mgr->get_logging();
    req->log_format(s, "getting op %d", s->op);
    op = handler->get_op(store); #這里根據request_method獲取到最終處理request請求的handler類型
    ...
    req->log(s, "pre-executing");
    op->pre_exec(); #請求預處理
    req->log(s, "executing");
    op->execute(); #具體請求的具體實現
    req->log(s, "completing");
    op->complete(); #完成請求處理


    #src/rgw/rgw_process.cc
    RGWHandler_REST* RGWRESTMgr_S3::get_handler(struct req_state *s)
    {
      bool is_s3website = enable_s3website && (s->prot_flags & RGW_REST_WEBSITE);
      int ret =
        RGWHandler_REST_S3::init_from_header(s,
    					is_s3website ? RGW_FORMAT_HTML :
    					RGW_FORMAT_XML, true);
      if (ret < 0)
        return NULL;
    
      RGWHandler_REST* handler;
      // TODO: Make this more readable
      if (is_s3website) {
        if (s->init_state.url_bucket.empty()) {
          handler = new RGWHandler_REST_Service_S3Website;
        } else if (s->object.empty()) {
          handler = new RGWHandler_REST_Bucket_S3Website;
        } else {
          handler = new RGWHandler_REST_Obj_S3Website;
        }
      } else {
        if (s->init_state.url_bucket.empty()) {
    		handler = new RGWHandler_REST_Service_S3; #bucket為空則切換到RGWHandler_REST_Service_S3
        } else if (s->object.empty()) {
    		handler = new RGWHandler_REST_Bucket_S3; #obj為空則切換RGWHandler_REST_Bucket_S3
        } else {
    		handler = new RGWHandler_REST_Obj_S3; #bucket和Object都不為空,則切換到RGWHandler_REST_Obj_S3
        }
      }
    
      ldout(s->cct, 20) << __func__ << " handler=" << typeid(*handler).name()
    		    << dendl;
      return handler;
    }


    #src/rgw/rgw_rest.cc
    RGWOp* RGWHandler_REST::get_op(RGWRados* store)
    {
      RGWOp *op;
      switch (s->op)  #這里s對應一個req_state的結構體
      { rest->op
       case OP_GET:
         op = op_get();
         break;
       case OP_PUT:
         op = op_put();
         break;
       case OP_DELETE:
         op = op_delete();
         break;
       case OP_HEAD:
         op = op_head();
         break;
       case OP_POST:
         op = op_post();
         break;
       case OP_COPY:
         op = op_copy();
         break;
       case OP_OPTIONS:
         op = op_options();
         break;
       default:
         return NULL;
      }
    
      if (op) {
        op->init(store, s, this);
      }
      return op;
    } /* get_op */


    結構體定義
    struct req_state {
      CephContext *cct;
      RGWClientIO *cio;
      RGWRequest *req; /// XXX: re-remove??
      http_op op; #對應一個枚舉類型,具體如下
      RGWOpType op_type;
      ...
    
      enum http_op {
      OP_GET,
      OP_PUT,
      OP_DELETE,
      OP_HEAD,
      OP_POST,
      OP_COPY,
      OP_OPTIONS,
      OP_UNKNOWN,
    };


URL->handler過程

理解整個URL轉換handler的過程,能夠感覺request信息快速定位具體的op操作,方便debug,整個過程用下面一張圖總結。

怎么理解RGW中request的處理流程

到此,關于“怎么理解RGW中request的處理流程”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武威市| 海口市| 无棣县| 互助| 宜昌市| 叶城县| 安西县| 贡觉县| 长岛县| 乾安县| 阿荣旗| 炉霍县| 临邑县| 泗阳县| 曲周县| 岳阳市| 普兰县| 麻阳| 长春市| 京山县| 临桂县| 新绛县| 五常市| 镇平县| 东安县| 永丰县| 顺昌县| 洛宁县| 庐江县| 乌苏市| 南江县| 正阳县| 阿勒泰市| 镶黄旗| 故城县| 鹿邑县| 广西| 灌云县| 济源市| 高尔夫| 金华市|