`

gluster分析(转)

阅读更多
引言
GlusterFS
是一个高层次的分布式文件系统解决方案。通过增加一个逻辑层,对上层使用者掩盖了下面的实现,使用者不用了解也不需知道,文件的存储形式、分布。内部实现
是整合了许多存储块(server)通过Infiniband RDMA 或者Tcp/Ip
方式互联的一个并行的网络文件系统,这样的许多存储块可以通过许多廉价的x86 主机,通过网络搭建起来。
其相对于传统NAS 、SAN、Raid 的优点就是:

容量可以按比例的扩展,且性能却不会因此而降低。

廉价且使用简单,完全抽象在已有的文件系统之上。

扩展和容错设计的比较合理,复杂度较低。扩展使用translator 方式,扩展调度使用scheduling 接口,容错交给了本地的文件系统来处理。

适应性强,部署方便,对环境依赖低,使用,调试和维护便利。

支持主流的linux 系统发行版,包括fc,ubuntu,debian,suse 等,并已有若干成功应用。
整体逻辑结构分析
GlusterFS,整体来看分客户和服务端两部分,当然这是相对的。

客户端是对于提供数据中心整体来说的,它对外提供文件服务,目录服务,两个文件系统最重要的两个服务。(注1:文件复制和共享的问题不知GlusterFS 是怎么考虑的)。

客户机拥有一个卷管理器,和子卷的调度程序,在客户机中有的子卷映像和服务器主机是相对的,1 对1。相当于一个卷集包含了若干逻辑卷,逻辑卷的物理位置是在服务器主机上的,该实现与NFS 是有很大区别的。

服务器主机,上面拥有与客户机相应的通信接口,接口之间使用GlusterFs protocol 来通信,服务器主机还应有自己的文件系统来提供文件服务和目录服务,GlusterFS 是构建在其上的。

当然客户和服务主机都有相应的配置文件,物理连接是通过InfiniBand、Myrinet 或者Gbit 以太网连接。下图为个人理解图:

组件构成分析

客户与服务器组件。这部分是复杂双方传输一个总的接口,服务器组件负责把自己的子卷发布出来,客户组件负责挂载GlusterFS 到内核的VFS 上。

翻译器模式, 一种来自GNU/Hurd的设计机制,(hurd 是借鉴IBM vms
系统设计的,内核只有最简单的功能,其上层设计了模拟器可以模拟很多操作系统)该设计可以扩展GlusterFS
的功能,包括调试器,性能调优的工具,加密验证等都是使用的该模式。xlators 文件夹下的都是翻译器的实现。

传输模块,protocol translators 文件夹是其实现。

调度模块,Scheduler 文件夹下面有4种调度器实现,其作用是对子卷做负载均衡。
4 种调度器实现了unify 翻译器。分别为:

Adaptive Least Usage (ALU) 利用它的一种评价方式,把一些要素如磁盘利用率、文件访问频率(读、写分开)、响应速度等综合起来考虑,做出的一种自适应的调度方式。其实现是4 种调度中最复杂的。

Non-Uniform Filesystem Scheduler 这个有点象NUMA ,一种结合SMP 和Mpp以及cluster 优点的内存管理方式,它的一个特点就是在创建文件时优先在本地创建文件。

Random scheduler 随机调度器,使用随机数发生器,选择子卷。

Round-Robin (RR) scheduler
螺旋线调度算法,它会将数据包均匀的分发给各台服务器,它把所有的服务器放在相等的地位上,而不会实际的去考虑各台服务器的差异,如负载,响应等等,如有
4 台服务器,调度序列可能就是ABCDABCDABCDABCD。。。
4 种基本模块构成了GlusterFS,另外还提供了一些扩展。
源代码组成分析
定量分析:37 个头文件,55 个c 源码文件,共有代码59460 行(包括源码中的空行)。文件最多的是libglusterfs 文件夹,包含了36 个文件。
启动过程
glusterfs_ctx_t(重要):GlusterFS 的环境类。里面包含日志文件,日志级别,定时器,poll 类型等等,使用dict 实现。服务端和客户端可以使用守护进程方式(deamon 精灵),也可以作为应用程序来启动。
下面剖析了两个部分的main 函数。
server部分(glusterfsd.c)初始化环境ctx,初始化调用池,初始化链表,解析命令行参数。
//main 部分
FILE *fp;
int32_t pidfd;
glusterfs_ctx_t ctx = { //这个东西比较常见,环境提供者,使用字典或//map 实现。
   .logfile = DATADIR "/log/glusterfs/glusterfsd.log",
   .loglevel = GF_LOG_ERROR, //日志级别,有点像log4j
   .poll_type = SYS_POLL_TYPE_MAX, //使用poll 方式?奇怪为什么不使用epoll
};
call_pool_t *pool;
pool = ctx.pool = calloc (1, sizeof (*pool));
LOCK_INIT (&pool->lock);
INIT_LIST_HEAD (&pool->all_frames);
argp_parse (&argp, argc, argv, 0, 0, &ctx);
设定进程pid,设定日志级别,文件路径。
pidfd = pidfile_lock (pidfile);
if (gf_log_init (ctx.logfile)
接下来设定系统资源限制,一般默认是1024,比如打开文件数,此处设定为65535.软限制和硬限制设为相等。
{
struct rlimit lim; //该结构体是系统内核提供的,含有两个成员
lim.rlim_cur = RLIM_INFINITY;
lim.rlim_max = RLIM_INFINITY;
if (setrlimit (RLIMIT_CORE, &lim)
接下来读取卷配置文件specfile 串,程序设定的是CONFDIR "/glusterfs-server.vol",成功了如何如何…..失败了如何如何……
if (specfile) {
   fp = fopen (specfile, "r");
   if (!fp) {
     gf_log ("glusterfsd",
     GF_LOG_ERROR,
     "FATAL: could not open specfile: '%s'",
     specfile);
   exit (1);
   }
} else {
     gf_log ("glusterfsd",
     GF_LOG_DEBUG,
     "main: specfile not provided as command line arg");
     argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
   exit (0);
}
然后是判断环境ctx 的foreground 有值与否,没有值,就清空命令行的参数值,然后把argv[0]填充成[glusterfsd],生成守候进程,更新前面锁定的pidfile。
if (!ctx.foreground) {
   int i;
   for (i=0;i
初始化定时器,通过specfile 串对应文件构造出树来,关闭该文件,忽略管道信号
SIGPIPE
设置软中断处理函数为glusterfsd_cleanup_and_exit 这个清理函数。
gf_timer_registry_init (&ctx);
xlator_tree_node = get_xlator_graph (&ctx, fp);// 从文件中构造解释器树,
//glusterfs.c 中有同名函数
if (!xlator_tree_node) {//判断生成结果
   gf_log ("glusterfsd",
     GF_LOG_ERROR,
     "FATAL: could not create node graph");
   exit (1);
}
fclose (fp);
/* Ignore SIGPIPE *///设置忽略的信号(sigpipe 管道)
signal (SIGPIPE, SIG_IGN);
#if HAVE_BACKTRACE //设置打印栈的信号处理
/* Handle SIGABORT and SIGSEGV */
signal (SIGSEGV, gf_print_trace);
signal (SIGABRT, gf_print_trace);
#endif /* HAVE_BACKTRACE */
signal (SIGTERM, glusterfsd_cleanup_and_exit);//设置软中断处理函数
最后进入循环,判断函数是transport.c 中的poll_iteration 函数。循环完毕关掉pidfile。
while (!poll_iteration (&ctx));
close (pidfd);
观察poll_iteration(&ctx)的实现,发现默认如果不设置ctx 的异步进程通信模式的话,默认是使用epoll 的,看代码:
//transport.c
int32_t
poll_iteration (glusterfs_ctx_t *ctx)
{
int32_t ret = 0;
#ifdef HAVE_SYS_EPOLL_H
switch (ctx->poll_type)
{
   case SYS_POLL_TYPE_EPOLL:
    ret = sys_epoll_iteration (ctx);
    break;
   case SYS_POLL_TYPE_POLL:
    ret = sys_poll_iteration (ctx);
    break;
   default:
    ctx->poll_type = SYS_POLL_TYPE_EPOLL;
    ret = sys_epoll_iteration (ctx);
    if (ret == -1 && errno == ENOSYS) {
    ctx->poll_type = SYS_POLL_TYPE_POLL;
    ret = sys_poll_iteration (ctx);
    }
    break;
  }
  #else
    ret = sys_poll_iteration (ctx);
  #endif
   return ret;
}
关于poll 和epoll 相关函数的实现都在poll.c 和epoll.c 里面。poll、epoll、select
是网络编程和进程间通讯的三种模式。select 在BSD Unix 中引入, 而poll是System V 的解决方案. epoll
调用添加在2.5.45, 作为使查询函数扩展到几千个文件描述符的方法。具体他们的区别可以查man 手册页。
Client 客户端启动过程:(glusterfs-fuse/glusterfs.c)
初始化glusterfs_ctx 环境中的日志文件位置,日志级别和poll 类型,这个和server端一样,另外声明了xlator 的图(树型),配置文件的指针,传输类型指针,还有就是系统资源限制,和调用池。
xlator_t *graph = NULL;
FILE *specfp = NULL;
transport_t *mp = NULL;
glusterfs_ctx_t ctx = {
   .logfile = DATADIR "/log/glusterfs/glusterfs.log",
   .loglevel = GF_LOG_ERROR,
   .poll_type = SYS_POLL_TYPE_MAX,
};
struct rlimit lim;
call_pool_t *pool;
同样需要设定系统资源限制的值,此处还可以设定debug 模式来使用mtrace()
#ifdef HAVE_MALLOC_STATS
#ifdef DEBUG
   mtrace ();
#endif
   signal (SIGUSR1, (sighandler_t)malloc_stats);
#endif
   lim.rlim_cur = RLIM_INFINITY;
   lim.rlim_max = RLIM_INFINITY;
   setrlimit (RLIMIT_CORE, &lim);
   setrlimit (RLIMIT_NOFILE, &lim);
初始化环境的调用池,解析参数等等这些和server 是一样的。
pool = ctx.pool = calloc (1, sizeof (call_pool_t));
   LOCK_INIT (&pool->lock);
   INIT_LIST_HEAD (&pool->all_frames);
argp_parse (&argp, argc, argv, 0, 0, &ctx);
此处与server 不同,但无非是一些判断和检测,如测试ctx 的日志文件设置没,设置glusertfs 的全局日志级别为环境的日志级别
if (gf_log_init (ctx.logfile) == -1) {
   fprintf (stderr,
   "glusterfs: failed to open logfile \"%s\"\n",
   ctx.logfile);
   return -1;
   }
   gf_log_set_loglevel (ctx.loglevel);
针对解析的参数设定mount_point,此处为判断设定与否。下面是设定端口号,和配置文件的地方等等,都是做检测用的。
if (!mount_point) {
   fprintf (stderr, "glusterfs: MOUNT-POINT not specified\n");
   return -1;
   }
if (!spec.where) {
   fprintf (stderr, "glusterfs: missing option --server=SERVER or --specfile=
   VOLUME-SPEC-FILE\n");
   return -1;
   }
if (spec.spec.server.port) {
   if (spec.where != SPEC_REMOTE_FILE)
      {
      fprintf (stderr, "glusterfs: -p|--port requires -s|--server option to be
      specified\n");
      exit (EXIT_FAILURE);
   }
}
下面是通过配置文件来设定ctx,接下来就是一些中断屏蔽,中断处理函数的处理等等,这个和server 是一样的。
specfp = get_spec_fp (&ctx);
if (!specfp) {
   fprintf (stderr,
   "glusterfs: could not open specfile\n");
   return -1;
}
/* Ignore SIGPIPE */
   signal (SIGPIPE, SIG_IGN);
#if HAVE_BACKTRACE
/* Handle SIGABORT and SIGSEGV */
   signal (SIGSEGV, gf_print_trace);
   signal (SIGABRT, gf_print_trace);
#endif /* HAVE_BACKTRACE */
接下来是当一切成员都初始化完毕时,此刻开始进行glusterfs 的挂载,下面和server
一样生成守护进程。然后注册定时器,生成xlator 树并赋值给环境ctx 中的graph 成员,初始化FUSE
的图,进入循环。后面的过程和server 类似,少许不同。所有的初始化过程都和ctx 环境有关,从携带变量,赋值等等,都是操作的ctx。
if (!(mp = glusterfs_mount (&ctx, mount_point))) {
   gf_log ("glusterfs", GF_LOG_ERROR, "Unable to mount glusterfs");
   return 1;
}
if (!ctx.foreground) {
/* funky ps output */
   int i;
   for (i=0;ixl = fuse_graph (graph);
// fuse_thread (&thread, mp);
while (!poll_iteration (&ctx));
return 0;
}
相关代码分析
传输协议代码
传输协议代码中体现了3 种可以使用的方式:

ib-verbs:使用Infiniband verbs 层为RDMA(Remote Direct Memory Access) 通信. 这是最快的接口(1-4 ms).

ib-sdp: 使用Infiniband SDP (sockets direct protocol) 为RDMA通信(70-90ms).

tcp:使用普通TCP/IP 或IPoIB 内部连接. 假如有4 节点的集群,每台主机的NIC 带宽1G byte/s ,那么组合起来的带宽也有4G byte/s。


下面是tcp 部分的分析:
共4 个文件tcp.h 是接口定义文件,里面定义了几个tcp 操作的函数,接收,关闭连接等等,还定义了等待队列的结构体wait_queue 和一个tcp 状态的结构体tcp_private。Tcp.c 是头文件里面定义的函数的实现。
Tcp-client.c:里面有关于建立连接的方法,tcp 客户端确认提交的方法,初始化传输和结束等方法。Tcp-server.c 里面也有相应的方法。
3 种方法都是按照transport.h 定义的接口来实现的。这里用到了面向对象的思想和状态模式,transport.c 里面的相关方法对其多种“子类做了”dispatch。
例如
//transport.c
int32_t
transport_notify (transport_t *this, int32_t event)
{
  int32_t ev = GF_EVENT_CHILD_UP;
  if ((event & POLLIN) || (event & POLLPRI))
    ev = GF_EVENT_POLLIN;
  if ((event & POLLERR) || (event & POLLHUP))
    ev = GF_EVENT_POLLERR;
    return this->notify (this->xl, ev, this);
}
该模块通过transport_op 这个结构体实现了“多态”,该结构体在transport.h 有接口定义(都是函数指针),而在每个连接方式的实现里面都声明一个实例,并按自己的方式初始化。
//transport.h
struct peer_info_t { //连接属性结构体含有套接字信息
   struct sockaddr_in sockaddr;
};
struct transport { //传输interface
   struct transport_ops *ops; //操作功能结构体指针,相当于类函数
   void *private; //私有信息,在子类中初始化
   void *xl_private; // 
   pthread_mutex_t lock; //线程锁
   int32_t refcount; //引用计数
   xlator_t *xl;
   void *dnscache; //dns 缓冲?作用不太明了
   data_t *buf; //数据缓冲
   int32_t (*init) (transport_t *this, //初始化函数
     dict_t *options,
     event_notify_fn_t notify);
   struct peer_info_t peerinfo; //包含了前面定义的套接字信息
   void (*fini) (transport_t *this); //“析构”函数
   event_notify_fn_t notify; //消息
};
struct transport_ops { //传输类的“成员函数“
   int32_t (*flush) (transport_t *this);
   int32_t (*recieve) (transport_t *this, char *buf, int32_t len);
   int32_t (*submit) (transport_t *this, char *buf, int32_t len);
   int32_t (*writev) (transport_t *this,
     const struct iovec *vector,
     int32_t count);
   int32_t (*readv) (transport_t *this,
     const struct iovec *vector,
     int32_t count);
   int32_t (*connect) (transport_t *this);
   int32_t (*disconnect) (transport_t *this);
   int32_t (*except) (transport_t *this);
   int32_t (*bail) (transport_t *this);
};
在真正的实现里面会初始化,传输类的成员函数的,如Tcp-server.c
//Tcp-server.c
struct transport_ops transport_ops = { //此处初始化transport 类的成员函数,这里是多态
// .flush = tcp_flush, //每个其具体实现都可以灵活定义自己的操作细节。
.recieve = tcp_recieve,
.disconnect = tcp_disconnect, //其具体实现也在本文件中。
.submit = tcp_server_submit,
.except = tcp_except,
.readv = tcp_readv,
.writev = tcp_server_writev
};
调度器剖析
调度器是给unify 的接口用的,在集群文件系统中,分数据块时绑定一个相应的调度器,来进行数据的分布式存取。有四种调度器,前面有提到了。调度操作接口比较简单,只要实现下列的接口函数的类就是一个调度器。
//scheduler.h
struct sched_ops { // 包括初始化,清理费料,更新,调度器逻辑,通知。
   int32_t (*init) (xlator_t *this);
   void (*fini) (xlator_t *this);
   void (*update) (xlator_t *this);
   xlator_t *(*schedule) (xlator_t *this, int32_t size);
   void (*notify) (xlator_t *xl, int32_t event, void *data);
};
该文件还定义了一个获得调度器的方法get_scheduler,具体实现在scheduler.c 里面,被unify.c 中调用(后面提unify.c).
RR 调度器是最简单的,和下面要写的xlator 关系很密切。结构体如下:
//rr.h
struct rr_sched_struct { //rr 调度需要的一些属性如刷新间隔,剩余磁盘空间,可用性等等。。
   xlator_t *xl;
   struct timeval last_stat_fetch;
   int64_t free_disk;
   int32_t refresh_interval;
   unsigned char eligible;
};
struct rr_struct { //rr 结构体
   struct rr_sched_struct *array; //包含rr 调度结构体的一个数组
   struct timeval last_stat_fetch;
   int32_t refresh_interval; //刷新时间间隔
   int64_t min_free_disk; //最小的剩余空间
   pthread_mutex_t rr_mutex; //线程锁
   int32_t child_count; //节点计数
   int32_t sched_index; //调度索引
};
与接口的联系方式和transport 模块类似,实现了sched_ops 定义的操作。
//rr.c
struct sched_ops sched = {
   .init = rr_init,
   .fini = rr_fini,
   .update = rr_update,
   .schedule = rr_schedule,
   .notify = rr_notify
};
xlator与xlator_list
Xlator 是一个有前驱和后继及父指针的节点类,其组成了xlator_list
链表,另外系统使用它组成树结构来使用,schedulor 在初始化时是会遍历xlator_list
的每个节点的。Xlator里面还包括了相关xlator
的操作符xlator_fops、xlator_mops,和构造函数与析构函数,以及一些必要的数据,节点表指针,消息,glusterfs
环境,配置选项字典(option)等等。
//xlator.h
struct _xlator {
   char *name;
   char *type;
   xlator_t *next, *prev;
   xlator_t *parent;
   xlator_list_t *children;
   struct xlator_fops *fops;
   struct xlator_mops *mops;
   void (*fini) (xlator_t *this);
   int32_t (*init) (xlator_t *this);
   event_notify_fn_t notify;
   dict_t *options;
   glusterfs_ctx_t *ctx;
   inode_table_t *itable;
   char ready;
   void *private;
};
typedef struct xlator_list {
   xlator_t *xlator;
   struct xlator_list *next;
} xlator_list_t;
Xlator_list 是一个关于xlator 的前向链表。
Translators与hurd/GNU
Translators 思路来自GNU/hurd 微内核的虚拟文件系统设计部分,一个translator
是一个用于目标服务器与hurd
分布式文件系统之间的普通程序。作用是对外部的文件系统做操作时,转换成目标文件系统适当的调用。Translators
不需要特别的权限运行。在传统的unix 内核设计上,文件系统或虚拟文件系统都是在内核里面实现的,内核有绝对的机器访问权,在hurd
上,使用的微内核设计,所以translator 使用的协议相关操作不需要特别权限来执行,在用户空间上执行。
Translator 可以附着在节点上,每个tanslator 都是针对相应的功能设计的,比如rot-13是加密用的,Trace 是追踪,调试用的,performance 文件夹下的4 个translator 是用来性能调优用的。
和translator 有直接关系的是这么几个文件,xlator.c 、xlator.h
、default.h、,default.c 四个文件,后两个比较容易解释,就是其他translator 在定义fop 和mop
时如果自己没有设定实现的话,便会使用默认实现,其实现就在这两个文件里面。也就是说这两个文件里面保含了所有的操作的定义。前两个文件在上节已经说过
了。
下图是glusterfs 使用的相关translator 所处的位置。相对于客户端来说,服务端的任务真的是很简单的,大部分translator 是工作在客户端的,比如,性能调优,调度器,合并器等等,而相反,服务端只需运行起来glusterfsd 就可以了。

要设计一个translator 也比较容易, 除了需要一个初始化函数
int32_t init (xlator_t *this)
和收尾的函数
void fini (xlator_t *this)
还需要对xlator.h 中的xlator_fops、xlator_mops 两个结构体中,需要翻译的命令自己定义。
//xlator_fops的定义,里面包括要求翻译的调用表,fops表示文件操作
struct xlator_fops {
   fop_lookup_t lookup; //前者是一个指向函数的指针
   fop_forget_t forget;
   fop_stat_t stat;
     …………
   fop_lk_cbk_t lk_cbk;
   fop_writedir_cbk_t writedir_cbk;
};
结构体中每个属性都是个指向函数的指针,例:
typedef int32_t (*fop_lookup_t) (call_frame_t *frame,xlator_t *this,loc_t *loc);
xlator_mops的定义,里面包括要求翻译的调用表,mops表示管理操作
struct xlator_mops {
   mop_stats_t stats;
   mop_fsck_t fsck;
   mop_lock_t lock;
   mop_unlock_t unlock;
   mop_listlocks_t listlocks;
   mop_getspec_t getspec;
   mop_stats_cbk_t stats_cbk;
   mop_fsck_cbk_t fsck_cbk;
   mop_lock_cbk_t lock_cbk;
   mop_unlock_cbk_t unlock_cbk;
   mop_listlocks_cbk_t listlocks_cbk;
   mop_getspec_cbk_t getspec_cbk;
};
前面是需翻译的命令,翻译后的命令例子如下,以rot-13 为例:
//rot-13.c 下面的赋值表示要翻译的两个调用, 管理操作以默认不做更改
//(default.h,default.c)
struct xlator_fops fops = {
   .readv = rot13_readv,
   .writev = rot13_writev
}; //这里赋值结构体的方式是C99标准新出来的,其在linux2.6内核源码中有较多的使用。
struct xlator_mops mops = {
};
同样你把自己需要翻译过来的调用自己实现例如下:
static int32_t
rot13_writev (call_frame_t *frame,
   xlator_t *this,
   fd_t *fd,
   struct iovec *vector,
   int32_t count,
   off_t offset){ do something }
这样扩展一个translator 就完成了。
translator 操作是异步的,这样可以减少网络上调用的延时造成性能下降。
它使用STACK_WIND 和'STACK_UNWIND 维护一个用户空间的调用栈。在桩文件callstub.h
文件中,里面有call_stub_t 结构体的定义,结构体里面含有一个联合,另外头文件还有相关调用的桩,call -stub.c
里面是头文件接口的实现。
// call-stub.h
typedef struct {
   struct list_head list;
   char wind;
   call_frame_t *frame;
   glusterfs_fop_t fop;
   union { //联合体里面包含了若干个结构体,其中每个结构体里面都是一个调用桩
             //是一个指向函数的指针,和相关需要传递或保存的属性或结构(像函数对象?)。
/* lookup */
   struct {
     fop_lookup_t fn;
     loc_t loc;
   } lookup;
……….
} args;
} call_stub_t;
// call-stub.c 头文件中示例的实现
call_stub_t *
fop_lookup_stub (call_frame_t *frame,
   fop_lookup_t fn,
   loc_t *loc)
{
   call_stub_t *stub = NULL;
   stub = stub_new (frame, 1, GF_FOP_LOOKUP);
   if (!stub)
     return NULL;
   stub->args.lookup.fn = fn;
   loc_copy (&stub->args.lookup.loc, loc);
   return stub;
}
server-protocol/client-protocol
Glusterfs 使用的协议是比较简单的,协议的定义可以在其官方网站有简短的描述。
(来自代码注释protocol.h)
All value in bytes. '\n' is field seperator.
Field:
==================
"Block Start\n":12
callid:16
Type:8
Op:8
Name:32
BlockSize:32
Block:
"Block End\n":10
==================
起始头12 个字节,调用id 16 个字节,操作类型8 个字节,操作指令8 个字节,操作名32 个字节,数据块大小32 个字节,然后是数据块,然后是包尾10 个字节。
操作类型有四种:分别是请求和回应、对应当fop(文件操作),mop(管理操作)
typedef enum {
   GF_OP_TYPE_FOP_REQUEST,
   GF_OP_TYPE_MOP_REQUEST,
   GF_OP_TYPE_FOP_REPLY,
   GF_OP_TYPE_MOP_REPLY
} glusterfs_op_type_t;
操作指令定义在glusterfs.h 里面两个枚举类型,一个fop,一个mop。
服务端执行的是响应请求,所以收到的包中操作类型皆是request 类型的fop 或者mop,然后将之交给一个解释器函数,函数负责分析是fop 还是mop,然后转换成local系统的执行序列。这其中还包括一些传输的错误处理,参数不正确等等。
该解释器通过调用相应的本地函数,处理完后返回的也是一个完整的协议数据包。
该函数在server-protocol.c 文件中,声明如下:
static int32_t
server_protocol_interpret (transport_t *trans,gf_block_t *blk)
此外服务端还需要维护一个响应队列。
客户端就比较繁琐了,它需要负责连接,保持连接,握手等动作,另外它还和服务端一样,也有一个翻译器,负责解释收到的协议包的处理。
由于客户端对其上层应用来说还得提供文件服务,所以它所需要提供的xlator_fops对象的成员函数比服务端提供的更多一些。

该图是服务端与客户端建立连接之后,客户端请求一个命令,或传输一部分数据所需的过程示意图,最中间的部分是在网络中传输的协议包。顶部是客户端请求的指令,该指令一般是给更高层提供服务的。最下层是服务端处理请求的命令或数据给local 调用处理。
相关的实用工具类
Util 类:dict 、stack、list,自己实现的容器和必要的操作。Stack 用的是list 实现的。
hashFn: 实现的一个最快速hash 算法, uint32_t SuperFastHash (const char * data, int32_t len)这个方法,来自网上一个实现。
Lock:加锁,解锁的类。
Logging:日志类,到文件的。
rot-13:简单的一个加密类,没有错误检查的。
Timer:定时器,记时器
性能,优化的部分代码
整体上,增加性能的优化方式就是利用缓冲,加之考虑其业务需求,比如频繁读写小文件,或是大量操作是读文件而很少写等等。利用其业务特点,适当的使用优化方式,源代码里面提供了4 种优化器,都是利用了translator 模式实现的。
Readhead:预读技术,这个在操作系统中内存技术,外存技术和catch 技术中用到比较多了。大概的意思就是使用临近数据被访问的可能性较大的原理,做的预读的优化。
Writebehind:后写技术,就是当需要回写硬盘时,先做一个缓冲区,然后等缓冲区满了,一次性写回硬盘,这样减少了使用系统调用,网络等开销。
Io-cache:这个是利用多个服务端中多余内存来做缓冲用的,网站上有个性能测试,64 个服务端主机,每主机有8GB
mem,使用io-catche 后,每个主机使用了6GB mem作为io 缓冲,共有64×6GB =384GB
的数据缓冲区,这样可以大大减少外存的访问,提高了数据访问速度。
Io-threads:io 线程化,AIO 添加了异步读写功能,使用这个translator,可以利用系统的idle
进程堵塞时间来处理新到来的请求。当进入内核调用时系统会锁住资源,如cpu mem 等等,这样就不能利用其做其他工作了,该translator
可以更好的改进此模型,是之更有效率。看其road map 是1.3 版本新加进来的特性。
在cluster 文件夹下面有两个与性能有关的三个translator。
分片技术strip:这个大意就是象RAID0 那样,可以加速保存和读取,但风险加大,所以在Stripe.c 文件的注释中,提示最好和下面的translator 一起使用,以保证安全。
重复技术afr:这个就是象RAID1 那样,保存时写数据做双份。而且可以对相应的类型的文件做不同的设置。
Unify:组合了多个存储块到一个巨大的存储空间里面,前面介绍translator 时有写unify 在整个系统中所处的位置。
当然对单个主机中文件系统的优化也是需要的,比如对ext3,reiserfs 的参数优化。
全局看整个系统
此处写的是个人体验,不一定都正确,供参考。
Glusterfs 是一个存储空间和访问效率都可以线性增加的一个分布式文件系统,网上资料除了gluster.org 以外,几乎没有什么有关的介绍了。
通过对源码的审阅,个人感觉,比较主要的是把程序的整体结构理清,扩展方式弄明白在向下看具体的实现是比较好的。
该系统扩充的方式是使用了translator 的模式,具体我还参考了《现代操作系统》中分布式文件系统章节和GNU/HURD 中解释translator 的部分,后者主要是在gnu 的网站上。
数据结构上讲,整个文件系统中节点构成了一棵树,而且每个节点的操作是通过某个translator
来工作的,一个节点可以附着很多的translator。所有的translator都要实现xlator
结构体和相关的xlator_fops、xlator_mops
两个“成员函数的结构体”,从xlator“继承”下来的操作如果不自己定义,那么就会使用默认的设置,这个在default.c
里面定义。当然自己定义的操作并赋值,这个过程有些象子类覆盖父类的操作,平行来看也就是多态。当然这是从面向对象角度来看的,该系统很多地方都使用了面
向对象的思想来设计的,这个和linux 2.6 以后的内核模块设计是异曲同工的。
那么一般可以这样识别一个用c 实现的Class 关键字的类:
例(对源文件有些修改):
struct A {
   char *name;
   char *type; //成员
   struct A *this; //this 指针
   struct xlator_fops *fops; //成员操作结构体1
   struct xlator_mops *mops; //成员操作结构体2
   void (*fini) (struct A *this); // 析构函数,垃圾清理
   int32_t (*init) (struct A *this);//构造函数,初始化
   event_notify_fn_t notify; //成员。。
   dict_t *options;
   glusterfs_ctx_t *ctx;
   inode_table_t *itable;
   char ready;
   void *private;
};
1.一个struct 定义里面包含一个指针该指针的类型是该struct 定义的类型。
2.上面的struct 内部成员中含有其他结构体的指针,象xlator_fops 就是这里提到的其他结构体的指针,该结构体里面全部都是指向函数的指针,也就是成员函数了。
当然此处也可以把xlator_fops 里面的成员都释放到struct A 里面, 但是这样这个struct 就显得有些臃肿了,,毕竟成员函数还是不少的。上面这个例子还有两个只有类才具备的析构函数,和构造函数。
glusterfs_ctx 控制了全局的信息,很多地方传输都是使用它来传递的,一个典型的环境类。初始化些东西也是针对它来做的。
Redhat GFS 和Glusterfs 的目的类似,都是以全局在一个命名空间下而通过访问其他节点获取数据的。此处没有性能比较。
Lustre 也是一个开源基于GNU lisence 的集群文件系统,网站资源比较丰富,开发者的资源也比较多,中文资料也不少,sun 公司收购了clusterfs 公司,拥有了此技术。
下面地址显示的是lustre 与glusterfs 做相当命令所需时间的比较:
http://www.gluster.org/docs/index.php/GlusterFS_1.3.pre2-VERGACION_vs_Lustre-1.4.9.1_Various_Benchmarks
下面的地址是NFS 与glusterfs 性能的测试对比:
http://www.gluster.org/docs/index.php/GlusterFS_1.2.1-BENKI_Aggregated_I/O_vs_NFSv4_Benchmark
分享到:
评论

相关推荐

    gluster源码分析

    ### GlusterFS源码分析 #### 一、GlusterFS概览 GlusterFS是一种分布式文件系统,设计用于实现高性能和高扩展性。它能够支持大规模的数据存储需求,适用于多种应用场景,如云存储、大数据处理等。在进行深入的源码...

    Gluster targets Hadoop opportunity with GlusterFS 3.3 beta

    GlusterFS作为一款分布式文件系统,其最新版本3.3 beta版提供了与Hadoop的...Gluster的这一举措,将有助于推动分布式文件系统与大数据分析、云存储技术的进一步融合,为用户带来更多的灵活性和高性能的存储解决方案。

    大数据揭秘

    - **File Systems**:如HDFS(Hadoop Distributed File System)、Gluster、GPFS等,提供了高效的数据存储和访问机制。 - **NoSQL Databases**:如HBase、Cassandra、MongoDB等,适合处理非结构化或半结构化数据。 -...

    Hadoop生态环境(一).docx

    Red Hat在2011年收购了Gluster后,将其整合到其产品线中,提供了商业支持。 - **QFS**:QFS是针对MapReduce任务的分布式文件系统,设计用于提供优于HDFS的性能和成本效率。它使用Reed-Solomon纠错技术,仅需1.5倍...

    NX二次开发-属性操作(创建与编辑)

    目前关于属性操作的创建于编辑主要有新旧两个版本,旧版本主要使用UF_ATTR_assign()函数,新版本主要使用UF_ATTR_set_user_attribute()函数。注意在使用新版本是需要初始化。

    编书 机械制图习题集(属性块图框)出版社.dwg

    编书 机械制图习题集(属性块图框)出版社.dwg

    毕业设计物联网实战项目基于 ESP8266 及 1.3 寸 TFT 实现的华为太空人时钟.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    【机器人控制】基于MATLAB的不同神经网络控制器性能对比:机器人手臂模型的NNPC、MRC和NARMA-L2控制策略分析(复现论文或解答问题,含详细可运行代码及解释)

    内容概要:本文档提供了三种神经网络控制器(NNPC、MRC和NARMA-L2)在机器人手臂模型上性能比较的MATLAB实现代码及详细解释。首先初始化工作空间并设定仿真参数,包括仿真时间和采样时间等。接着定义了机器人手臂的二阶动力学模型参数,并将其转换为离散时间系统。对于参考信号,可以选择方波或正弦波形式。然后分别实现了三种控制器的具体算法:MRC通过定义参考模型参数并训练神经网络来实现控制;NNPC利用预测模型神经网络并结合优化算法求解控制序列;NARMA-L2则通过两个神经网络分别建模f和g函数,进而实现控制律。最后,对三种控制器进行了性能比较,包括计算均方根误差、最大误差、调节时间等指标,并绘制了响应曲线和跟踪误差曲线。此外,还强调了机器人手臂模型参数的一致性和参考信号设置的规范性,提出了常见问题的解决方案以及性能比较的标准化方法。 适合人群:具备一定编程基础,特别是熟悉MATLAB编程语言的研究人员或工程师,以及对神经网络控制理论有一定了解的技术人员。 使用场景及目标:①理解不同类型的神经网络控制器的工作原理;②掌握在MATLAB中实现这些控制器的方法;③学会如何设置合理的参考信号并保证模型参数的一致性;④能够根据具体的性能指标对比不同控制器的效果,从而选择最适合应用场景的控制器。 其他说明:本文档不仅提供了完整的实验代码,还对每个步骤进行了详细的注释,有助于读者更好地理解每段代码的功能。同时,针对可能出现的问题给出了相应的解决办法,确保实验结果的有效性和可靠性。为了使性能比较更加公平合理,文档还介绍了标准化的测试流程和评估标准,这对于进一步研究和应用具有重要的指导意义。

    《基于YOLOv8的雪场设备识别系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    (源码)基于Python的微信智能聊天机器人.zip

    # 基于Python的微信智能聊天机器人 ## 项目简介 本项目是一个基于Python的微信智能聊天机器人框架,旨在通过ChatGPT的强大对话能力,将微信打造成一个智能助手。该机器人支持私聊和群聊的智能回复、语音识别、图片生成、插件扩展等功能,能够与好友进行多轮对话,并提供丰富的交互体验。项目支持多端部署,包括个人微信、微信公众号和企业微信应用。 ## 项目的主要特性和功能 多端部署支持个人微信、微信公众号和企业微信应用等多种部署方式。 智能对话支持私聊和群聊的智能回复,具备多轮会话上下文记忆功能,支持GPT3、GPT3.5、GPT4等模型。 语音识别可识别语音消息并通过文字或语音回复,支持Azure、Baidu、Google、OpenAI等多种语音模型。 图片生成支持图片生成和图生图功能(如照片修复),可选择DALLE、Stable Diffusion、Replicate等模型。

    Android毕设实战项目基于Android的健身信息管理系统.zip

    【项目资源】: 适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    《基于YOLOv8的医疗废物分类系统》(包含源码、完整数据集、可视化界面、部署教程)简单部署即可运行。功能完善、操作简单,适合毕设或课程设计.zip

    资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。

    毕业设计物联网实战项目基于腾讯云物联网开发平台的智能台灯,全套腾讯解决方案,可使用微信小程序远程控制.zip

    【项目资源】: 物联网项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    scipy-0.11.0.tar.gz

    该资源为scipy-0.11.0.tar.gz,欢迎下载使用哦!

    【机械故障仿真】PT500PLUS平行轴齿轮箱故障测试台Machine Vibration & Gearbox Simulator(机械振动-齿轮箱模拟器):转子及齿轮传动故障模拟与数据采集系统设计

    内容概要:PT500PLUS平行轴齿轮箱故障测试台是由瓦伦尼安(VALENIAN)Machine Vibration & Gearbox Simulator(机械振动-齿轮箱模拟器)开发的专业机械故障仿真测试设备。该测试台旨在模拟和研究转子、齿轮传动、轴承及电机系统中的多种常见故障,包括但不限于轴不对中、转子不平衡、机械松动、轴承故障、齿轮故障(如点蚀、磨损、断齿等)以及电机故障(如转子不平衡、轴承故障、匝间短路等)。测试台配备有先进的传感器和数据采集系统,能够实时采集并分析振动、噪声、转速、扭矩等参数,提供多通道同步信号采集与频谱分析功能。此外,测试台还配备了10寸触摸屏、PLC智能控制系统和急停按钮,确保操作简便和安全。 适用人群:机械工程专业师生、科研人员以及从事机械故障诊断和维护的技术人员。 使用场景及目标:①用于高校和科研机构的教学和研究,帮助学生和研究人员深入理解机械故障的机理;②为企业提供故障诊断和预防性维护的解决方案,提高设备可靠性和运行效率;③通过模拟真实工况下的故障,进行轴承寿命预测性试验,研究轴承故障机制与轴承载荷、转速、振动、温度之间的关系。 其他说明:测试台结构紧凑,模块化设计,便于移动和维护。它不仅支持多种传感器的安装和数据采集,还提供了丰富的分析软件功能,如FFT频谱分析、轴心轨迹图、小波分析等,支持数据导出和二次开发,适用于各种复杂的研究和应用需求。

    ### 【5G智慧文旅】商业街、水街信息集成方案:5G技术赋能全方位智慧化升级与游客体验优化

    内容概要:本文档详细介绍了XXX5G特色商业街的规划设计方案,旨在通过5G技术与物联网等前沿科技的融合,全方位提升游客体验感和街区运营效率。首先,基础信息系统涵盖综合管理智慧平台、统一结算系统、5G视频智慧安防监控系统等多个子系统,实现多系统协同管理和数据安全保障。其次,特色应用方面,推出5G短信服务、5G智慧机器人、5G无人巡逻车、5G+XR时空走廊、5G+元宇宙体验馆等项目,将尖端科技与深厚文化底蕴巧妙结合,创新文旅体验形式。最后,通过5G高清视频直播与分享、5G+高空文旅等举措,进一步提升水街的影响力和吸引力。 适用人群:本方案适用于文旅项目规划者、商业街运营管理者、信息技术从业者以及对智慧城市建设感兴趣的各界人士。 使用场景及目标:①为商业街提供全面的智慧化升级方案,涵盖基础信息系统和特色应用两大部分;②通过5G技术赋能,实现高效运营管理和沉浸式游客体验;③推动文旅产业创新发展,促进地方经济繁荣和社会进步。 其他说明:该方案不仅关注技术实现,更重视用户体验和服务质量,强调文化传承与科技创新的有机结合,致力于打造具有国际影响力的智慧文旅新地标。

    【更新至2023年】2000-2023年中国气候政策不确定性指数(全国、省、市三个层面)

    【更新至2023年】2000-2023年中国气候政策不确定性指数数据(全国、省、市三个层面) 1.时间:2000-2023年 2.来源:使用人工审计和深度学习算法MacBERT模型,基于中国《人民日报》《光明日报》《经济日报》《环球时报》《科技日报》《中国新闻社》等6家主流报纸中的1,755,826篇文章,构建了2000年1月至2023年12月的中国全国、省份和主要城市层面的CCPU指数。研究框架包括六个部分:数据收集、清洗数据、人工审计、模型构建、指数计算与标准化以及技术验证。 3.范围:中国、省、市三个层次 4.参考文献:Ma, Y. R., Liu, Z., Ma, D., Zhai, P., Guo, K., Zhang, D., & Ji, Q. (2023). A news-based climate policy uncertainty index for China. Scientific Data, 10(1), 881. 5.时间跨度:全国层面:日度、月度、年度;省级层面:月度、年度;地级市层面:月度、年度

    毕设单片机实战项目基于STM32F401和ESP8266的硬件开源物连网平台.zip

    【项目资源】: 单片机项目适用于从基础到高级的各种项目,特别是在性能要求较高的场景中,比如操作系统开发、嵌入式编程和底层系统编程。如果您是初学者,可以从简单的控制台程序开始练习;如果是进阶开发者,可以尝试涉及硬件或网络的项目。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 # 注意 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担。 2. 部分字体以及插图等来自网络,若是侵权请联系删除。

    机械工程BTS200轴承寿命预测测试台Bearing Prognostics Simulator:多功能加载与润滑系统设计及应用反映了文档的核心内容

    内容概要:BTS200轴承寿命预测测试台是一款专为研究轴承寿命预测及加速磨损过程设计的实验设备。该设备结构灵活,支持不同尺寸和类型的轴承测试,最大负载可达15000N。测试台采用先进的伺服电缸加载系统,能够在轴向和径向上精确施加载荷,并配备高精度测力传感器和温度监测系统,确保实验数据的准确性。此外,BTS200还拥有油液循环润滑系统,通过油膜减少摩擦和磨损,保持机械部件在适宜的工作温度范围内,延长轴承寿命。Bearing Prognostics Simulator(实验台可通过触控屏操作,支持多速运行(0-3000RPM),并具备过热保护机制,在温度超过150℃时自动停机。BTS200广泛应用于轴承寿命预测、故障机制研究以及剩余寿命预测模型的开发。 适合人群:轴承设计研发人员、机械工程研究人员、高校实验室师生及相关领域工程师。 使用场景及目标:①研究轴承在不同载荷和转速条件下的磨损特性;②开发和验证轴承剩余寿命预测模型;③探索轴承故障机制及其对系统性能的影响;④评估不同润滑方式对轴承寿命的影响。 其他说明:BTS200测试台不仅提供硬件支持,还配备了完整的软件控制系统,包括PLC闭环控制、温度监测反馈模块等,确保实验过程的稳定性和数据的可靠性。此外,设备支持快速安装和拆卸测试轴承,便于实验操作。

    AXI Memory Mapped to PCI Express (PCIe) Gen2 v2.9

    xilinx基于PCIE IP的PCIE Bridge IP操作手册

Global site tag (gtag.js) - Google Analytics