1.服务端(glusterfsd),客户端(glusterfs),管理程序(glusterd)同一main入口
首先,glusterfs这个框架类似于网络协议栈框架,xlator结构体就是代表一个功能层(相当于一个网络协议层), 这个glusterfsd.c:main 主要就是搭建起xlator这棵树和必要的资源,具体功能在的相应的xlator中,可以看出该架构垂直扩展,添加功能很容易 。即这个main就是通用的初始化流程, 该程序是服务端还是客户端等等,就看这颗树是咋迭堆xlator的。 相关源码分析资料参考(大体流程没啥出入):glusterFS源码结构分析.pdf - 下载频道 - CSDN.NET
GlusterFS 主函数工作流程_百度文库
2. xlator 架构
glusterfs架构最核心的结构体, xlator就相当于用c语言实现的对象(OO), 参考 GlusterFS:xlator基础源码研究 这篇写的就很好了。 此外,个人觉得,看源码时候,适时用面向对象思想看,不要只跟数据流走,走通不意味着理解深刻,比较好。 这里主要说明: 1 .IO流中, 相关的xlator中未定义的文件系统POSIX接口是用defaults.c中默认的。 2. 每个xlator可以看做对象, 都有notify函数,既都会有被通知发生了事件并做相应的处理, 这个就有些观察者模式意思。让别人对此感兴趣的人来调用,通知该层的xlator发生了啥事件,然后该xlator就做相应的动作,源码理解就是外部调用该xlator的notify函数,我想这也是借鉴网络协议栈思想。 默认的notify是在defaults.c:default_notify函数, 默认调用parent的notify:3. STACK_WIND ()跟STACK_WIND_TAIL()宏主要区别就是否复用parent的call_frame_t结构体。call_frame_t可以看做该层xlator的上下文(每次接口调用)。
4.可以看到采用这架构,垂直来看,扩展功能很容易,只要追加一层xlaor就行了而且不影响;水平角度看来,太对称了,会增加实现复杂度吧。各有利弊吧。 有机会看看ceph,好好对比。。。
3 .mem_pool && hash
mem_pool采用的思想就是linux内核的slab思想 ,本质就是空间换时间思想,hash本质思想也如此,印象中,glusterfs挺多结构体组织就是采用hash链表来管理的,典型就是glustefs中 inode && entry&& inode_tables。 我想,hash在文件系统跟交换机上有很大的应用场景吧,毕竟在追求高效率下,空间换时间思想是经常采用的。参考GlusterFS之内存池(mem-pool)实现原理及代码详解, GlusterFS 主函数工作流程_百度文库 这篇也有相关实现章节,个人觉得实现采用“malloc+slab思想”。
4. 线程池
glusterfs自己实现的线程池,也有自己的简单线程调度机制, 也算多并发来提高glusterfs的性能吧, synctask_new()即创建一个synctask,可以看到挺多地方用到的:我想采用线程池技术 多用在服务端,毕竟可以充分利用多核多cpu来提高并发,来提高处理速度。可以看到RPC server端的rpcsvc_handle_rpc_call函数中也调用到了。5. RPC模块
glusterfs自己实现RPC协议框架,作为各个主机上的进程间通信基础。 可以参考 Glusterfs之rpc模块源码分析(中)之Glusterfs的rpc模块实现(1) 系列,分析比较细了,不过主要以数据流分析为主, 看完后跳出来用面向对象看待相关结构体直接关系,效果比较好,对其他模块也试用 。补充一点 :
1. 服务端 rpcsvc_program结构体中的synctask 变量作用是否使用多线程,值为synctask true,即使用线程池来处理,提高服务端处理效率进而提高性能:
实际代码(在rpcsvc_handle_rpc_call):
6.event_pool
事件管理池,在使用tcp/ip协议下,主要由socket.c这个文件夹使用, 抽象统一管理每个socket连接, 实现对于 每个socket连接 采用同步非阻塞式;event_register()来注册事件通知的载体,这里采用epool或pool ,默认采用epool: 可以看到glusterd.c:main 最后将阻塞死循在 event_dispatch (ctx->event_pool) 。即:event_dispatch_epoll函数 。(采用pthread_cond_wait +epoll_wait 实现 ,基本都这样实现框架的吧)7 . IO流入口
主要有3个入口(FUSE,NFS,libgfapi), 参考 GlusterFS分布式文件系统 (下图来自此处): 1.FUSE 客户端调用mount.glusterfs时,如图,使用fuse方式,fuse是用户空间文件系统常用接口,由于用户态和内核态切换且拷贝数据,会影响性能。源码分析 &疑问: 追踪调试,可以发现fuse使用自己的协议,当GF_EVENT_CHILD_UP等事件来时,fuse-bridge.c :notify()调用线程 fuse_thread_proc()来处理,该函数是单线程死循环,是接口调用处理入口: readv(/dev/fuse) //接受数据,然后分析并处理协议 fuse_ops[finh->opcode] (this, finh, msg); //最后调用具体的接口。
疑问:跟我在网上搜索到的标准fuse接口协议不一样,只要open(/dev/fuse),就可以使用自己的协议,不受内核fuse模块接口协议影响? 即内核fuse跟glusterfs咋交互的,比较迷惑)
2. libgfapi 如图客户程序调用libgfapi,就避免数据多次在用户态和内核态拷贝和切换,会提高一定的性能。
源码入口比较简单,就是调用相关的API就行了,看源码例子就了解了:glfsxmp.c。
3 .NFS没看过追踪过。不过也是glusterfs自己实现或基于第三方模块剪裁修改过的吧。 上链接:Glusterfs之nfs模块源码分析(中)之Glusterfs实现NFS服务器系列(该blog主glusterfs系列文章还是很不错的。)
待续 。。。。