溫馨提示×

溫馨提示×

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

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

glusterfs通信rpc怎么用

發布時間:2022-01-05 09:11:18 來源:億速云 閱讀:170 作者:iii 欄目:云計算

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

在glusterfs中,gluster與glusterd通信請求對卷的操作、集群的操作、狀態的查看等;glusterd與glusterfsd通信完成對卷的操作,集群的操作,狀態的查看;glusterfs與glusterfsd通信完成文件的存儲。所有這些通信都是通過內部的RPC模塊來完成的。

=========================================

從代碼的組織來看,RPC的服務端邏輯上可分為四層,server-app、rpc-server、rpc-transport、protocol,每一層都提供相應的接口供上一層調用,同時,上一層會提供回調函數供下一層來調用;同樣,RPC的客戶端邏輯上也可分為四層,cli-app、rpc-cli、rpc-transport、protocol。目前,protocol提供了tcp(socket)和rdma兩種方式,且都以動態庫的方式提供,rpc-transport會根據配置加載不同的動態庫。我們以gluster與glusterd的通信并選用tcp的方式為例來看看RPC相關流程。

1. 服務端的初始化

需要注意的是:rpc_transport_load時會根據協議的類型加載(使用dlopen)不同的動態庫,調用socket_listen時將fd與回調函數添加事件驅動器中。當有讀寫事件時,事件驅動器回調socket_server_event_handler函數(用于服務端的accept)或者socket_event_handler函數(用于一般的請求),然后依次回調rpc_transport_notify、rpcsvc_notify處理RPC請求。

2. 客戶端的初始化

socket_connect函數會將fd以及回調處理函數注冊到事件驅動器中。

3. 一次完整的RPC流程

(1) 客戶端發送RPC請求

客戶端通過調用rpc_clnt_submit函數發送RPC請求,該函數又會一層層調用,最終在socket_submit_request中通過writev將請求發送出去。在調用rpc_clnt_submit時會準備好RPC所需要的相關數據,例如程序號,程序版本號,過程號,參數信息等等,然后逐層按照接口組織好相關的數據。

例如: 執行 gluster volume info命令,其內部關鍵代碼:

int32_t gf_clie_1_get_volume(call_frame_t * frame, xlator_t * this)
{
    ...
    ret = cli_cmd_submit(&req,
                         frame,
                         cli_rpc_prog, //包含程序名,程序號,程序版本號等信息
                         GLUSTER_CLI_GET_VOLUME, //過程號
                         NULL,
                         this,
                         gf_cli3_1_get_volume_cbk, //結果處理回調函數
                         (xdrproc_t)xdr_gf_cli_req);
    ..
}

int cli_cmd_submit(void *req, call_frame_t * frame,
                   rpc_clnt_prog_t * prog, int procnum,
                   struct iobref * iobref,
                   xlator_t * this, fop_cbk_fn_t cbkfn,
                   xdrproc_t xdrproc)
{
    ...
    ret = cli_submit_request(req, frame, prog, procnum, NULL, this,
                             cbkfn, xdrproc);
    ...
}

int cli_submit_request(void * req, call_frame_t * frame,
                       rpc_clnt_prog_t * prog, int procnum,
                       struct iobref * iobref,
                       xlator_t * this, fop_cbk_fn_t cbkfn,
                       xdrproc_t xdrproc)
{
    ...
    ret = rpc_clnt_submit(global_rpc, prog, procnum, cbkfn,
                          &iov, count, NULL, 0, iobref, frame,
                          NULL, 0, NULL, 0, NULL)
}

int rpc_clnt_submit(struct rpc_clnt * rpc,
                    rpc_clnt_prog_t * prog, int procnum,
                    fop_cbk_fn_t cbkfn,
                    struct iovec * proghdr, int proghdrcount,
                    struct iovec * progpayload, int progpayloadcount,
                    struct iobref * iobref, void * frame,
                    struct iovec * rsphdr, int rsphdr_count,
                    struct iovec * rsp_payload,int rsp_payload_count,
                    struct iobref * rsp_iobref)
{
    struct iobuf * request_iob = NULL;
    rpc_transport_req_t req;
    ...
    request_iob = rpc_clnt_record(rpc, frame, prog, procnum, proglen,
                                  &rpchdr, callid);
    req.msg.rpchdr = &rpchdr;
    req.msg.rpchdrcount = 1;
    req.msg.proghdr = proghdr;
    req.msg.proghdrcount = proghdrcount;
    req.msg.progpayload = progpayload;
    req.msg.progpayloadcount = progpayloadcount;
    req.msg.iobref = iobref;
    ...
    ret = rpc_transport_submit_request(rpc->conn.trans, &req);
    ...
}

int32_t rpc_transport_submit_request(rpc_transport_t * this,
                                     rpc_transport_req_t * req)
{
    ret = this->ops->submit_request(this, req);
}

int32_t socket_submit_request(rpc_transport_t * this,
                              rpc_transport_req_t * req)
{
    struct ioq * entry = NULL;
    entry = __socket_ioq_new(this, &req->msg);

    ret = __socket_ioq_churn_entry(this, entry);
    ...
}

int __socket_ioq_churn_entry(rpc_transport_t *this,
                             struct ioq * entry)
{
    ret = __socket_writev(this, entry->pending_vector,
                          entry->pending_count,
                          &entry->pending_vector,
                          &entry->pending_count);
    ...
}

int __socket_writev(rpc_transport_t * this,
                    struct iovec * vector, int count,
                    struct iovec **pending_vector, int *pendint_count)
{
    ret = __socket_rwv(this, vector, count, pending_vector,
                       pending_count, NULL, 1);
    ...
}

int __socket_rwv(rpc_transport_t *this, struct iovec *vector,
                 int count, struct iovec **pending_vector,
                 int * pending_count, size_t * bytes, int write)
{
    int opcount = 0;
    struct iovec * opvector = NULL;

    opvector = vector;
    opcount = count;
    while(opcount)
    {
        if(write)
        {
            ret = wrtiev(sock, opvector, opcount);
        }
        ...
    }
    ...
}

(2) 服務端處理RPC請求

服務端收到請求后,從socket_event_handler回調到rpc_transport_notify,再回調到rpcsvc_notify,最終調用rpcsvc_handle_rpc_call函數。在這個函數中,解析客戶端RPC請求中包含的程序號,過程號以及相關參數等,然后根據這些程序號,過程號找到對應的處理函數。而這些處理函數就是先前通過rpcsvc_program_register函數注冊的。對應的處理函數處理完成后調用相關函數答復客戶端。

注: actor并不是一個真正的函數,僅標識不同RPC請求的處理函數.

(3) 客戶端處理RPC的回復

客戶端在發送請求時,會將請求的相關信息緩存下來,當收到服務器的回應后,再根據程序號、過程號找到對應的請求信息,然后調用相應的回調函數對請求結果進行處理。

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

向AI問一下細節
推薦閱讀:
  1. GlusterFS 相關
  2. GlusterFS

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

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女