您好,登錄后才能下訂單哦!
這篇文章主要介紹“glusterfs通信rpc怎么用”,在日常操作中,相信很多人在glusterfs通信rpc怎么用問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”glusterfs通信rpc怎么用”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
在glusterfs中,gluster與glusterd通信請(qǐng)求對(duì)卷的操作、集群的操作、狀態(tài)的查看等;glusterd與glusterfsd通信完成對(duì)卷的操作,集群的操作,狀態(tài)的查看;glusterfs與glusterfsd通信完成文件的存儲(chǔ)。所有這些通信都是通過(guò)內(nèi)部的RPC模塊來(lái)完成的。
=========================================
從代碼的組織來(lái)看,RPC的服務(wù)端邏輯上可分為四層,server-app、rpc-server、rpc-transport、protocol,每一層都提供相應(yīng)的接口供上一層調(diào)用,同時(shí),上一層會(huì)提供回調(diào)函數(shù)供下一層來(lái)調(diào)用;同樣,RPC的客戶(hù)端邏輯上也可分為四層,cli-app、rpc-cli、rpc-transport、protocol。目前,protocol提供了tcp(socket)和rdma兩種方式,且都以動(dòng)態(tài)庫(kù)的方式提供,rpc-transport會(huì)根據(jù)配置加載不同的動(dòng)態(tài)庫(kù)。我們以gluster與glusterd的通信并選用tcp的方式為例來(lái)看看RPC相關(guān)流程。
1. 服務(wù)端的初始化
需要注意的是:rpc_transport_load時(shí)會(huì)根據(jù)協(xié)議的類(lèi)型加載(使用dlopen)不同的動(dòng)態(tài)庫(kù),調(diào)用socket_listen時(shí)將fd與回調(diào)函數(shù)添加事件驅(qū)動(dòng)器中。當(dāng)有讀寫(xiě)事件時(shí),事件驅(qū)動(dòng)器回調(diào)socket_server_event_handler函數(shù)(用于服務(wù)端的accept)或者socket_event_handler函數(shù)(用于一般的請(qǐng)求),然后依次回調(diào)rpc_transport_notify、rpcsvc_notify處理RPC請(qǐng)求。
2. 客戶(hù)端的初始化
socket_connect函數(shù)會(huì)將fd以及回調(diào)處理函數(shù)注冊(cè)到事件驅(qū)動(dòng)器中。
3. 一次完整的RPC流程
(1) 客戶(hù)端發(fā)送RPC請(qǐng)求
客戶(hù)端通過(guò)調(diào)用rpc_clnt_submit函數(shù)發(fā)送RPC請(qǐng)求,該函數(shù)又會(huì)一層層調(diào)用,最終在socket_submit_request中通過(guò)writev將請(qǐng)求發(fā)送出去。在調(diào)用rpc_clnt_submit時(shí)會(huì)準(zhǔn)備好RPC所需要的相關(guān)數(shù)據(jù),例如程序號(hào),程序版本號(hào),過(guò)程號(hào),參數(shù)信息等等,然后逐層按照接口組織好相關(guān)的數(shù)據(jù)。
例如: 執(zhí)行 gluster volume info命令,其內(nèi)部關(guān)鍵代碼:
int32_t gf_clie_1_get_volume(call_frame_t * frame, xlator_t * this) { ... ret = cli_cmd_submit(&req, frame, cli_rpc_prog, //包含程序名,程序號(hào),程序版本號(hào)等信息 GLUSTER_CLI_GET_VOLUME, //過(guò)程號(hào) NULL, this, gf_cli3_1_get_volume_cbk, //結(jié)果處理回調(diào)函數(shù) (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) 服務(wù)端處理RPC請(qǐng)求
服務(wù)端收到請(qǐng)求后,從socket_event_handler回調(diào)到rpc_transport_notify,再回調(diào)到rpcsvc_notify,最終調(diào)用rpcsvc_handle_rpc_call函數(shù)。在這個(gè)函數(shù)中,解析客戶(hù)端RPC請(qǐng)求中包含的程序號(hào),過(guò)程號(hào)以及相關(guān)參數(shù)等,然后根據(jù)這些程序號(hào),過(guò)程號(hào)找到對(duì)應(yīng)的處理函數(shù)。而這些處理函數(shù)就是先前通過(guò)rpcsvc_program_register函數(shù)注冊(cè)的。對(duì)應(yīng)的處理函數(shù)處理完成后調(diào)用相關(guān)函數(shù)答復(fù)客戶(hù)端。
注: actor并不是一個(gè)真正的函數(shù),僅標(biāo)識(shí)不同RPC請(qǐng)求的處理函數(shù).
(3) 客戶(hù)端處理RPC的回復(fù)
客戶(hù)端在發(fā)送請(qǐng)求時(shí),會(huì)將請(qǐng)求的相關(guān)信息緩存下來(lái),當(dāng)收到服務(wù)器的回應(yīng)后,再根據(jù)程序號(hào)、過(guò)程號(hào)找到對(duì)應(yīng)的請(qǐng)求信息,然后調(diào)用相應(yīng)的回調(diào)函數(shù)對(duì)請(qǐng)求結(jié)果進(jìn)行處理。
到此,關(guān)于“glusterfs通信rpc怎么用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。