集群架构当中,NFS 恐怕是一个很麻烦的瓶颈点
鸟哥的研究当中,经常需要使用到集群架构 (cluster) 的系统来进行平行协作处理,这种情况底下,简单的系统架构, 大多是将所有的重要数据通通放置到一个 Storage 当中,再将其他的运算主机通过 NFS 连接到该系统,就简单的达到了平行处理可以操作的环境。 简易架构示意图如下:
NFS (/home, /data) +------+----+-------+--------+ Node1 Node2 Node3 Node4 Node5
请注意,为了『平行处理』的机制,所有的上面系统,全部的系统架构都需要相同!最好 node1~node5 这 5 部能够是相同的硬件设备, 能够拥有相同的帐号/密码 (连 UID/GID 等等都需要相同),相同的操作系统 (连内核版本都要相同),这样运作程序时, 比较不容易出现问题。当然,还需要其他额外的平行处理函数库,那个不在这里讨论,有兴趣的自行 google 一下 mpi 与平行化, 大概就有很多文章说明了。
既然感觉这么简单,系统操作上面应该没啥问题吧?对啊!如果以每一部 node 自行运算,使用了自己的 mpi 程序自己的 cpu 内核计算, 那几颗 CPU 内核都没啥问题!可以安全的处理所有的程序,不会被中断。鸟哥使用的最新的系统,是 AMD 64 内核的架构, 这种架构下,最多可以用到 64 内核来跑程序,速度还不赖,很是开心。
问题是,既然有这么多部系统,如果只要跑一个案例,能不能大家一起来跑?例如上面说得,如果我有 64 内核的系统 3 部, 难道不能拿 192 个内核来跑嘛?理论上,应该是可以的!所以,鸟哥就拿来跑啦!但是...先不管跑出来的速度会不会比较快, 光是 3 台 64 内核同时跑,就出问题了!没办法顺利运作结束!老是可能随机断到某个运算日期...非常怪。
基本上,运算这种平行处理,大概有两种机制,一种是连续跑,一种是分日跑。假设我要运作的平行处理程序,需要运作 30 日仿真, 第一种方式是,30 日的仿真量,一次跑完,从第 1 日跑到第 30 日这样连续跑;第二种则是分 30 次跑,每次跑 1 日的份量。
各有优缺点,只是站在开发者的角度,目前大多使用 1 日跑的情境来处理。那么这种情境会发生什么问题呢?为什么这种方法老是产生中断呢? 大致上我们可以这样看:
上述的问题发生在第 2 及第 5 点,当系统初始化的情况。基本上,文件系统为了加速,通常数据不会立刻写入到磁盘当中,而是暂时存放于内存。 这种机制在单一系统上面是没问题的,但是如果用于上述的状况,那就惨了:
看到问题的发生了嘛?这是数据访问的问题~当 node1 初始化并且产生大家都要读写的数据时,为了加速,所以尚未写入 NFS storage 当中。 结果这时却又要 node2, node3 去 NFS 读取刚刚创见的文件!夭寿啦!又要马儿跑,又要马儿不吃草,所以,这个时候就挂点了...
那么该如何处理这个问题呢?鸟哥测试过每一部 node 系统上面使用 NFS 挂载的 lookupcache=none 的参数,结果虽然有好一些, 不过,还是有可能会随机中断。为什么呢?明明 NFS 文档说, lookupcache=none 代表随时去抓 NFS storage 的 cachec 而不是使用自己的 cache 啊! 话是这么说没错,针对 node2, node3 这点是没问题的!但是针对主办单位的 node1 来说,除非你修改了 Linux kernel 的 filesystem 设置参数, 否则的话,那个 lookupcache 指的是针对 NFS 的读写而已,并不是针对自己本身系统的操作,所以, node1 在 NFS 挂载为 lookupcache=none 的情境下, 依旧会将自己产生的文件暂存于自己的内存中,并不会立刻直接写回 NFS storage 喔!
NFS mount 有个机制,通过 sync 这个机制来处理,那么 node1 使用到任何 NFS 的设备数据时,都会同步写入到 NFS 文件系统中, 这不像 lookupcache 喔!只是,如此一来, node1 的读写,就会非常的延迟!因为 sync 对于 NFS 的性能来说,影响非常大!但是,这种设计方式最简单! 而且几乎不会出错!
这样说好了,既然大家都要读写 node1 这个主事者的系统,那么将 storage 换到 node1 不就好了?好啊!但是, NFS storage 通常不会在运算主机上, 这是因为很多很多考量...这里就不写了。那怎办?没关系,我们可以将已经挂载到 node1 的 NFS 目录,再次分享出去,然后让 node2, node3 挂载 node1 的数据,这样 node2, node3 就不需要 lookupcache,而 node1 也不需要 sync 喔! 只是从 node1 分享的 NFS 目录,需要在 /etc/exports 里面加上 crossmnt 这个参数才行!否则就可能读不到挂载的信息。 这点比较需要留意而已。
过去开机都是先将 Storage 开机完毕,之后每部 node 都是独立运作可以自由开机!但是如果使用这种方式,那么就得要先从 NFS storage 开机, 完成之后才能开机 node1,之后才能 node2 与 node3 等其他系统...尤其,如果你想要从 node2 作为主事者,那么整个挂载就得要重来... 在系统的运作上面,就会产生许多困扰!虽然性能上面会比较好一些。