引言
个人认为Gluster有5大基础组件,分别是:MGMT,RPC Server,RPC Client, NFS Server,NFS Client
这5个组件组成了Gluster的基本服务,所以这一章节就是简单概述下MGMT做了哪些事情
MGMT,NFS,RPC-Server都使用相同的main函数(glusterfsd:main),所以这3类都有着相同加载流程,大致流程如下:
int main (int argc, char *argv[])
{
…….
ctx = glusterfs_ctx_new();
ret = glusterfs_globals_init ();
ret = glusterfs_ctx_defaults_init (ctx);
ret = parse_cmdline (argc, argv, ctx);
ret = logging_init (ctx);
gf_proc_dump_init();
ret = create_fuse_mount (ctx);
ret = daemonize (ctx); //变成daemon进程
ret = glusterfs_volumes_init (ctx); //这个函数里干的事情,非常重要
ret = event_dispatch (ctx->event_pool); //分发事件,参考3.3
}
从ctx的出现频率,拍脑袋都能想到ctx是一个非常重要的结构,它保存了许多的信息,至于有哪些,再以后的章节再进行扩展,但在这main里,前面所有的调用都是为2个重要的函数做铺垫
1、 glusterfs_volumes_init()
2、 event_dispatch()
在glusterfs_volumes_init() 里配置了不同的xlator(通过volfile-id,来决定配置哪些xlator),在gluster里xlator都是以一个模块化的组件.so的形式存在的,存放方路径是
所以加载不同的xlator,就等于加载了不同的glusterfsd的服务。
三种模式
Gluster有3种运行模式,分别是:
GF_SERVER_PROCESS,GF_GLUSTERD_PROCESS,GF_CLIENT_PROCESS
虽然3个命令指向的是同一个文件(参考图1-1),但是这个文件确有3种模式
static uint8_t
gf_get_process_mode (char *exec_name)
{
char *dup_execname = NULL, *base = NULL;
uint8_t ret = 0;
dup_execname = gf_strdup (exec_name);
base = basename (dup_execname);
if (!strncmp (base, "glusterfsd", 10)) {
ret = GF_SERVER_PROCESS; (VOLUME,NFS,RPC Server)
} else if (!strncmp (base, "glusterd", 8)) {
ret = GF_GLUSTERD_PROCESS; (Daemon)
} else {
ret = GF_CLIENT_PROCESS; (RPC Client)
}
GF_FREE (dup_execname);
return ret;
}
解析命令行参数
利用了argp包,解析命令行顺序,具体详情参考
http://www.gnu.org/software/libc/manual/html_node/Argp-Examples.html#Argp-Examples
#0 parse_opts(key=16777219, arg=0x0, state=0x7fffffffce70) at glusterfsd.c:780
#1 0x00007ffff62cfc9bin argp_parse () from /lib64/libc.so.6--这是个so里的函数
#2 0x0000000000409001in parse_cmdline (argc=6, argv=0x7fffffffe578, ctx=0x617010) atglusterfsd.c:1793
#3 0x000000000040a1dfin main (argc=6, argv=0x7fffffffe578) at glusterfsd.c:2296
Event_dispatch
在glusterfs_ctx_defaults_init里被初始化
在gluster里使用了大量的函数指针,所以如何找到指针对应的函数,非常有助于代码的阅读,下面2个struct,定了对应的event函数
//event.h
struct event_ops {
struct event_pool * (*new) (int count,int eventthreadcount);
int (*event_register) (structevent_pool *event_pool, int fd,
event_handler_thandler,
void *data, intpoll_in, int poll_out);
int (*event_select_on) (structevent_pool *event_pool, int fd, int idx,
int poll_in,int poll_out);
int (*event_unregister) (structevent_pool *event_pool, int fd, int idx);
int (*event_unregister_close) (structevent_pool *event_pool, int fd,
int idx);
int (*event_dispatch) (structevent_pool *event_pool);
int (*event_reconfigure_threads)(struct event_pool *event_pool,
intnewcount);
int (*event_pool_destroy) (structevent_pool *event_pool);
};
//event-epoll.c
struct event_opsevent_ops_epoll = {
.new = event_pool_new_epoll,
.event_register = event_register_epoll,
.event_select_on =event_select_on_epoll,
.event_unregister = event_unregister_epoll,
.event_unregister_close = event_unregister_close_epoll,
.event_dispatch = event_dispatch_epoll,
.event_reconfigure_threads =event_reconfigure_threads_epoll,
.event_pool_destroy = event_pool_destroy_epoll
};
不管那种模式,都使用epoll,并在event-dispatch分发事件
event_pool->ops->event_dispacth这里是函数指针的调用,参考structops的真正指向是event_dispatch_epoll,并利用一个单独的线程worker去处理所有事件
XLATOR的加载
在默认情况下,glusterd会使用/etc/glusterfs/glusterd.vol来初始化xlator
1:volume management
2: type mgmt/glusterd
3: optionrpc-auth.auth-glusterfs on
4: option rpc-auth.auth-unixon
5: option rpc-auth.auth-nullon
6: optionrpc-auth-allow-insecure on
7: optiontransport.socket.listen-backlog 128
8: option event-threads 1
9: option ping-timeout 0
10: option transport.socket.read-fail-log off
11: optiontransport.socket.keepalive-interval 2
12: option transport.socket.keepalive-time 10
13: option transport-type rdma
14: option working-directory /var/lib/glusterd
15:end-volume
其中xl指向是当前的xlaotor(mgmt),glusterd.c:init()
在glusterd.c:init()里初始化了RPC服务
不同的xlator组成的堆栈结构,称为一个graph