这篇文章主要介绍“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怎么用”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。