使用 coLinux 和 openMosix 构建异构集群

发表于:2007-07-04来源:作者:点击数: 标签:
您可以通过以下三种方法的任意一种来创建一个集群:完全迁移到一个单一的平台,部分迁移,或者是以混合的方式创建。在本文中,将学习如何通过集群代理实现最后一种方法,并了解如何将 coLinux 和 openMosix结合起来为异构环境提供高性能集群中间件。在这个异
您可以通过以下三种方法的任意一种来创建一个集群:完全迁移到一个单一的平台,部分迁移,或者是以混合的方式创建。在本文中,将学习如何通过集群代理实现最后一种方法,并了解如何将 coLinux 和 openMosix结合起来为异构环境提供高性能集群中间件。在这个异构的环境中,Linux™ 将提供稳定性和性能,而且 Windows®用户可以继续使用他们的应用程序,根本不用关心其中的区别。

您可以通过以下三种方法的任意一种来创建一个集群:完全迁移到一个单一的平台,部分迁移,或者是以混合的方式创建。在本文中,将学习如何通过集群代理实现最后一种方法,并了解如何将 coLinux 和 openMosix结合起来为异构环境提供高性能集群中间件。在这个异构的环境中,Linux™ 将提供稳定性和性能,而且 Windows®用户可以继续使用他们的应用程序,根本不用关心其中的区别。

从九十年代早期起,集群计算已经取得了长足的发展。随着对 GNU/Linux 使用的日益增加,以可接受的预算使用 PC集群来获得超级计算速度正日趋主流。容易获得的廉价硬件(处理器、内存、硬盘、以太网卡等),再加上开放源代码软件,这些都促使人们采用基于Linux 的 Beowulf 集群。(“Beowulf”指的是基于 PC 的集群领域中最早的研究者 Dr. Donald Becker 和Dr. Thomas Sterling 为他们最初的集群所起的名字;很多人使用这个名字来代表一种类似的技术,即基于 PC 的集群。)

术语的这一模糊性带来了这样的问题:“希望构建集群的人是否必须使用 Linux?”(或许,那个问题的中心,也是更为实际的一点,是“我们有很多使用 Windows 的空闲 PC。仅仅为了借用 CPU 周期,我们是否需要将它们全部迁移到 Linux?”)

正是这些问题促使我们去试验如何构建混合式集群(hybrid cluster),即由异构操作系统构成的集群。本文使用的是 Windows 和 Linux,为了简化起见,没有考虑其他操作系统。

为什么创建混合式集群?
当前,局域网和校园网都是由使用不同操作系统的PC 所构成。有的使用 Windows,有的使用 Linux,还有的使用 BSD,等等。一个局域网中 PC 的平均数目在 100 到 300之间,这表明其中有巨大的潜在计算能力,特别是如果您正在规划一个主要目的是获得最高速度的高性能计算集群(HPC)。

这种类型的集群所面临的挑战是:在大部分情况下,我们不能让每台 PC百分之百地致力于集群的工作。传统的集群在全天候的运行期间内都完全致力于运行需要大量运算的程序,与之相比,这种混合式的集群主要适用于扩展现有Linux 集群的节点。实现这一目标有两种策略:

  • 在每一台 Windows PC 上安装集群代理(cluster agent)。您可以认为这个代理是在系统中运行的一个小应用程序,或者是一个 Windows 服务。它以自动的方式工作,其操作由主节点(使用 Linux)完全控制。
  • 使用双引导安装,或者使用 Linux LiveCD。LTSP(Linux Thin Server Project)也可以归类于此策略。其基本思想是将节点临时转换为 Linux 系统,然后作为集群的成员连接到主节点。

我们并没有将从 Windows 到 Linux的部分或完全迁移作为解决方案来研究,因为我们希望在本文中集中关注第三种方法。我们没有研究向 Linux的完全或者部分迁移,而是希望研究那些不需要关注完全迁移就可以将 Window 和 Linux加入集群的机制和好处。不过,这并不表示完全迁移是错误的解决方案。

我们选择集群代理方法作为解决方案,因为它具有以下优势:

  • Windows 用户能够继续在熟悉的环境中工作,使用办公套件、绘图或者执行其他任务。用户可以让集群代理以低优先级运行,或者在启动屏幕保护程序时运行。Seti@home 项目使用了此类策略,非常有效。
  • 由于避免了双引导,不需要进行重新分区(为了安装 Linux)。您可以在 Windows 文件系统之上安装 Linux (比如 ZipSlack),但这样会要求您必须退出 Windows。

使用集群代理的方法,您只需要在 FAT32 或者 NTFS 文件系统中留出一些空间来存放 Linux 代理二进制程序。

混合式集群的先决条件
在创建集群的过程中,需要在三类集群中作出选择:高可用集群(HA)、高性能计算集群(HPC)和高吞吐率集群(HTC)。我们选择的是 HPC,这是最常用的集群,它会带来以下后果:

  • 忽略在节点上可能发生的故障。这些故障包括电源故障、网线损坏以及其他种类的硬件相关问题,比如磁盘损坏、CPU 由于过热而被锁,以及内存损坏。
  • 各个节点在执行主节点所提交的作业时,需要重新引导的机率较小。在这种情况下,应用程序本身或者管理员必须在特定时间内重新启动必要的应用程序或者检查点。

让我们退而考虑这个问题:“为什么我们需要植入一个集群代理?难道将基于 Linux 的应用程序移植到 Windows 不能获得更好的性能吗?”当然,随着 MinGW 或 Cygwin 等跨平台编译器的可用,这可能会很容易。

对这个问题的回答是,我们出于以下原因而更希望使用集群代理:

  • 将软件移植到另一个平台不会像预期的那样顺利。对系统调用、时间、直接硬件访问等问题的处理会延缓实现。
  • 混合式集群往往用作各种新应用程序的实验台,或者用作对已有集群的扩展。投入很多精力来进行移植,对计划会经常变化的环境而言不会有太多好处。
  • 实际上,很多人使用商业或者私有软件。这种软件出售或发布时并没有附带源代码。结果是不可能进行移植。

我们提出的解决方案并不是要获得如同将其移植为本地 Windows 应用程序那样快的执行速度。不过请记住,在这个试验中,我们将尝试达到以下几个关键目标:

  • 灵活性。当代理以较低的优先级运行,或者只有在 CPU 的空闲周期中运行时,Windows 用户才可能如往常一样工作。
  • 性能。当运行集群代理时,执行速度应该几乎 与本地移植一样快。
  • 效率。我们只需要像安装普通 Windows 程序一样安装集群代理的二进制程序,并让它们自动运行。
  • 易管理。借助大规模部署软件(比如 LanDesk 套件,或者微软软件管理服务器(Microsoft Software Management Server)),我们可以快速安装和删除代理软件包。如果需要,还有 VNC 等远程 X 客户机扩展可以简化远程管理。

选择软件
首先,我们需要选择两个软件:

  • 模拟器或者虚拟机
  • 集群中间件

关于模拟器/虚拟机
该软件将成为一个桥梁,让 Linux 内核可以在 Windows 上运行;这是它的主要功能。

由于难以将单一系统映像(Single System Image,SSI)中间件移植到 Windows内核体系结构中,所以我们选择使用模拟器或者虚拟机。SSI解决方案会修改内核的几乎所有部分:进程管理、文件系统、内存管理、调度器,等等。通过不加修改地运行内核进程,模拟器简化了部署工作。

关于集群中间件
使用中间件,我们可以选择作为 Linux 内核扩展的解决方案,这样就可以构建 SSI 集群。还有其他一些选择(比如批调度器或者完全的远程执行包装器),但是我们选择 SSI 模型,因为它具有以下优势:

  • SSI 中间件隐藏了访问分散在节点间的资源(文件、内存、CPU)的复杂性。我们只是需要运行应用程序,中间件将透明地完成资源的管理。
  • SSI 中间件具有负载均衡和透明进程(transparent process)特性。利用这些特性,除了极其需要进行调整情形,或者中间件无法实现公平,管理员不需要手工调整负载。进程迁移也方便了执行,因为我们不需要进行显式的远程执行。

选择集群中间件
这相对简单。我们所选择的 SSI 中间件是什么?有三个开放源代码而且遵循 GPL 许可的解决方案(排序不分先后):

  • openMosix。
  • openSSI。
  • Kerrighed。

关于各个解决方案的详细资料超出了本文的范围,不过可以在参考资料中找到。

我们将选择 openMosix,原因有二:

  • 与其他解决方案相比,openMosix 拥有最为简单的配置。这将降低集群部署的复杂度。
  • openMosix 以其最简单的方式为我们提供了负载均衡和透明进程迁移功能。所谓“最简单”,指的是内核补丁的大小相对较小,而且没有引入很多特性。这适用于我们的试验,不过如果愿意的话,您可以使用其他 SSI 中间件来扩展此试验。

选择模拟器/虚拟机
这一选择略为复杂。有两种可能,使用 VMWare等商业版本的,或者使用 coLinux等开放源代码的(猜猜我们将选择哪一个!)。同样,我们选择的是基于开放源代码的解决方案。不过,我们首先来讨论各个解决方案的优势与不足,您将了解到在分析我们的选择时思考的过程。

对于商业产品,我们以 VMWare 为例。您可能会熟悉此产品;VMWare 已经在 VM 舞台活跃了很长时间。这里是我们对 VMWare 的初步分析。

优势 所在:

  • VMWare是一个完全的系统模拟器(在本文中,术语“模拟器(emulator)”和“仿真器(virtualizer)”可以自由互换,都是指“完成对某个系统的模拟的软件”)。所以,它可以模拟一个完整的系统(内存、存储器、CPU、以太网卡、声卡,等等)。运行于模拟器中的系统(称为客户系统(guest system))不需要任何修改(或者,最多需要一些保证 OS 平稳工作的补丁)。
  • 模拟器在与其他宿主应用程序隔离开来的内存地址空间中运行,与用户空间应用程序具有相同的特权,所以客户系统的任何破坏都不会影响宿主。

不足 之处:

  • 由于 VMWare 是一个商业产品,所以它不是免费的。网络中所有 Windows 机器的许可费用,可能很容易超出一个新的专用集群的费用,后者可以以更少的费用获得更高的性能。
  • 模拟器会消耗宿主系统的大量资源。模拟器不得不为 guest-kernel-to-application 通信拦截大部分指令,也不得不模拟一组完整的虚拟硬件设备。这样的模拟意味着使用多个层会影响网络延迟的正常下限,而这个下限是无法再下调的。
  • VMWare 本身(不包括客户系统)需要大量的内存。所以,分配给它的内存数量将会非常大。

现在来分析 coLinux。coLinux 是一个新的开放源代码解决方案,让您可以在 Windows 内核之上运行 Linux 内核。

优势

  • coLinux 让 Linux 内核可以在本地运行(作为 Windows内核驱动器)。由于在这宿主内核和客户内核之间没有任何“桥梁”,所以 Linux 客户可以以接近本地的速度运行。在很多不同的 Linux子系统中,模拟层是作为代码直接插入的,因此它们可以转换为对 Windows系统的直接请求。两个内核之间在内部执行上下文切换,但这可以非常快速地完成。
  • 宿主系统只需要分配完全只是客户系统(及其派生的进程)所需要的内存。

不足

  • coLinux 本身还在发展之中,所以在运行它时您可能会遇到一些小问题。尽管所有的开发人员都在尽力使 coLinux 变得更好,但他们也可能不能捕获某些缺陷Windows 2000 和 Windows XP 是得到支持的 Windows 版本
  • 要运行 coLinux,需要进行一些手工配置。当前还没有帮助创建完整 coLinux 系统的自动工具,所以您必须能够构建或调整 coLinux 配置。

那么,与 VMWare 相比,coLinux 的性能如何呢?我们运行了一个粗略的基准。作为测试,我们选择了来自 Povray 的 Web站点的 POV-Ray 3.6.1 预编译二进制程序。(POV-Ray 是逼真 3D图形创建软件的始祖之一,它完全由那些进行大量数字处理的任务构成,非常适合我们的测试。)使用 benchmark.ini(包含于 povray软件包之中)中的默认选项执行那个二进制程序: # povray benchmark.ini

POV-Ray 在用于 Linux 内核 2.4.26 的 coLinux 上运行。根文件系统使用的是 Gentoo发行版本。我们使用相同的发行版本在 VMWare 版本 4.5.2 上测试相同的 POV-Ray二进制程序。下面的表格说明了测试机器使用必要的选项(在 benchmark.ini 给出)完成预定义的场景所需要的时间。

表 1. POV-Ray 运行时间结果

平台(POV-Ray 在哪里执行)时间(单位为 分钟:秒)
本地 Linux39:23
coLinux39:26
VMWare40:53

研究数据表单,您会发现 coLinux 与本地 OS 的速度相差甚少。正如所预期的那样,VMWare 比 coLinux慢,相差一分钟左右。通过实时地将虚拟机(VM)的指令流翻译给宿主机器, VMWare 可以获得接近本地的速度,但是由于 VMWare本身在用户空间运行,这可能会引发问题。比如,当 VM 以内核模式执行代码时;为了正确地仿真 VM 的虚拟 CPU,VMWare必须谨慎地转换内存映射和权限。

现在,我们来看所选择的模拟器 coLinux 和所选择的中间件 openMosix 如何一起工作。

coLinux 与 openMosix 的联合
图 1 向我们展示了 openMosix 的工作方式。

图 1. openMosix 的工作方式
openMosix 的工作方式javascript:window.open(this.src);" style="CURSOR: pointer" onload="return imgzoom(this,550)">

openMosix 在 Linux 内核内部运行。它有若干个可以通过 /proc接口进行控制的参数。为了简化实际的操作,创建了一些用户空间应用程序。openMosix以分散的(decentralized)方式工作,所以在此拓扑中没有主节点或从节点。这一分散式策略被应用于负载信息交换,并且应用于进程迁移期间。

如果负载均衡算法认为另一个节点的工作负载较小,而且适于迁移进程,那么 openMosix会透明地将进程迁移到目标节点。进程不能或者不应该迁移的原因是多种多样的(使用pthreads、进行大量磁盘操作、运行期非常短)。从用户空间的角度来看,不需要修改应用程序代码。所有工作都在内核空间透明地完成。

现在,让我们来研究 coLinux 如何工作(下面的图引用自 coLinux.org)。

图 2. coLinux 内部结构的总体描述(获得了Dan Aloni 的授权,他是 coLinux 首席开发人员和文档编写者)
oLinux 内部结构的总体描述

Dan Aloni 将 coLinux 描述为一个协作的(cooperative)半虚拟的(paravirtualized)Linux 虚拟机。协作指的是它将控制权自主地交还给宿主 OS。半虚拟指的是:除了 CPU 和内存以外, coLinux内核不需接触任何实际的硬件。这与 VMWare 不同,后者截取访问硬件设备的 I/O 并模拟它。coLinux 感觉像是一个独立的 Linux机器 —— 客户内核的内部结构与宿主内核的内部结构是分开的。

注意,coLinux 由两部分构成:

  • 在宿主内核空间运行的 coLinux 内核驱动程序。
  • 若干个用户空间后台进程。

coLinux 内核驱动程序的主要工作是:

  • 在启动时加载 Linux 客户内核。您可以认为这个功能类似于引导加载器(比如 LILO 或 GRUB)。
  • 根据 colinux-daemon 进程的要求执行 ioctl() 请求。这个 ioctl() 调用负责进行客户 OS 与宿主 OS 之间的上下文切换。
  • 为来自某些虚拟驱动器(cobd(块设备)、conet(网络)、cocon(控制台))的中断和请求进行代理转发。

在用户空间中,最重要的是部分是 colinux-daemon-process。除了负责触发上下文切换之外,它还要作为colinux-console-nt 和 colinux-net-daemon 等一些其他后台进程的“管理者”。例如,通过colinux-console,用户可以查看 Linux 客户的活动控制台的当前显示。当用户在此 colinux-console 的shell 中输入或者执行命令时,colinux-daemon 将会 “包装”它并将其转发给 colinux-driver。要完全理解coLinux 的内部机制,请访问 coLinux.org。

openMosix 与 coLinux 融合时,没有显著的变化。由于 openMosix 完全位于内核空间,而 coLinux只是与通常一样引导客户内核映像,并如前所述那样工作。当 openMosix 必须与其他节点通信时,客户内核会去调用一些系统调用。coLinux截取这些调用,并将数据传递到 coLinux-net-daemon,由它来通过 Windows API 最终将数据发送出去。

下面是对 coLinux 网络层次和网络传输数据流的描述:

  1. 源应用程序(Source Application)
  2. Linux 内核
  3. coLinux 内核驱动程序
  4. coLinux 网络驱动程序
  5. Windows NIC 驱动程序

现在我们来看如何让 coLinux 和 openMosix 进行结合。

融合 coLinux 和 openMosix
对本文而言,我们组合使用了coLinux 和用于 2.4.26 Linux 内核的 openMosix 补丁。之所以选择2.4.26,是因为它是进行试验时最新的稳定内核版本,也是同时支持 openMosix 和 coLinux 的 2.4.x内核中序列号最高的版本。(这里提及的描述只是一个概述。要获得完整的说明,请参阅参考资料中的 step-by-step 指南。)

下面是制做您的第一个 coLinux/openMosix 内核的步骤:

  1. 您需要 2.4.26 Linux vanilla 内核,用于此内核的 openMosix,以及 coLinux 版本 0.6.1。下载所需要的存档文件,并将它们解压到合适的工作目录。
  2. 为内核源代码打上 coLinux 内核补丁,并将配置文件(conf/linux-config,这是 coLinux 所附带的)复制到内核源代码树。当然,应该将其命名为“.config”。
  3. 现在打 openMosix 补丁。有一个文件会失败,不过这没关系,因为它只是补丁认为有问题的一个 Makefile 文件。
  4. 最后,您可以执行下面的命令来构建内核:

    # make oldconfig
    # make dep
    # make vmlinux

这将生成 vmlinux 文件和新的内核。我们建议您在构建 coLinux 的所有过程中(内核映像和用户空间工具)都使用 gclearcase/" target="_blank" >cc3.3.x,因为已经证明它能够生成最稳定的二进制程序。编译内核映像和用户空间工具时不要使用不同的gcc,因为这可能会造成系统的锁定。为了将完成的内核用作虚拟机,还需要有用户空间工具、基文件系统的映像以及 TAP-32 win32网络驱动程序。为了缩短整个测试周期,您可以下载同时包含有用户空间工具和内核映像的立即可用的程序包。(在参考资料一节中可以找到所有这些下载。)

剩下的惟一一件事情就是创建您自己的文件系统映像,或者从 coLinux.org 下载它们。为了使用 openMosix 的功能,需要将openMosix 用户空间工具放入文件系统映像中。请参阅 openmosix.org Web 站点上关于如何编译用户空间工具的说明。

在 step-by-step 指南中,可以找到将所有内容(Linux 内核映像、用户空间工具、根文件系统等)整合为一个可用系统的步骤。

运行时间基准
这里是阐明我们所提出的方法的易用性与性能的一个基本的、初步的基准。我们的实验台上只有两台机器:Amun 是一台本地 Linux 的机器,运行的是 Debian linux。Ipc256 运行的是 Windows 2000 Professional。

各个节点的硬件规格如下:

Ipc256 的规格

处理器:P4 1.70 GHz
RAM:256 MB
操作系统:Windows 2000 Professional
硬盘:40 GB IDE
网卡:Realtek Semiconductor Co. Ltd. RTL-8139 Fast Ethernet

Amun 的规格

处理器:P4 2.40 GHz Hyper Threading
RAM:2048 MB
操作系统:Debian Woody
硬盘:2x approx. 40 GB IDE, several NFS mounts
网卡 1:Syskonnect (Schneider & Koch) SK-98xx V2.0 Gigabit Ethernet
网卡 2:Realtek Semiconductor Co., Ltd. RTL-8139 Fast Ethernet

我们选择了一个多进程(之所以使用术语“进程”,是因为它使用了 fork())应用程序作为基准,它不做任何事情,只是连续不断地使用不同的种子数值计算 Fibonacci 数字。它的目的并不是做有意义的计算,而是为我们的解决方案提供一个易于理解的说明。在下载一节中有压缩文件,下载这些文件可以查看其源代码。

程序分为两部分。第一部分派生 2^5 = 32 个子进程。为此它使用了系统调用 fork()。这样就使得 openMosix 可以将那些进程分布到参与集群的所有节点中去。在第二部分执行实际的计算。

我们将此程序运行了四次,取其平均值。下面的表给出了结果。

表 2. 多进程程序运行时间结果

宿主执行时间(单位为秒)注释
Amunta = 436.25本地运行
Ipc256ti = 778.75本地运行
Bothtb = 285.25先在 Amun 上运行,然后迁移到 Ipc256

查看这些结果,您会观察到单台 PC 完成那个工作需要多长时间。Amun 比 Ipc256 稍快一些,但是同时使用两台 PC 获得的效率绝对是最高的。如果不仅是一台而是很多 Windows PC 加入到集群,这个效率可能还会更高。

使用下面的公式计算开销:

Overhead = tb/ta + tb/ti - 1

在该例中,我们的试验所产生的开销是 2.01%,接近理论最优值。

通过这一基准,我们可以得出这样的结论:要最大限度地受益于此类集群,最好的方法就是划分作业或者应用程序。使用参数化调用(parameterized invocation) 是更常见的一个策略,使用不同的参数派生同一个程序的多个实例。

POV-Ray 的渲染工厂(renderfarm)是参数化调用的一个示例。渲染程序的每一个实例都取得一部分场景并构建出一个完成的帧。重复此过程,直到所有场景都被取完。

展望
对于预算充足的用户而言,采用 VMWare等商业化的仿真器或许是使用开放源代码的基于 Linux 的 SSI 来实现混合式 Windows-Linux集群的安全方法,但是,对那些寻求可接受的解决方案的用户而言,他们希望每一分投入都能获得最大的价值,而 coLinux 是理想的选择。

这一解决方案的优势很明显。不需要进行大规模的从 Windows 到 Linux 的迁移 —— 只需继续使用您所熟知的 Linux环境。这样将会缩短部署的时间,而且还能让基于 Windows 的用户如往常一样工作。Windows PC 的空闲能力可以用来帮助 Linux机器运行非常消耗 CPU 的程序。

基于目前基础的改进
今后能够得到改进的方面有很多,包括

  • 编写宿主内核和客户内核之间的内核到内核的网络数据包注入(injection)。当前,这些数据包必须从宿主驱动程序开始,经过 TAP32 驱动程序、colinux-net 后台进程、coLinux 后台进程,最后到达colinux 内核驱动程序。绕开这些步骤并将其替换为直接的内核驱动程序/colinux驱动程序连接,这样就可以减少通信延迟,从而提高集群的性能。
  • 创建更先进的集群代理软件包。有一些让我们可以立即部署的特殊的 coLinux 发行版本(下一节中提到的 CosMos 就是一个例子)。创建这样的软件包需要大家的共同帮助,最好让它拥有一个易用的配置管理器,使得用户或者管理员只需要点击几次鼠标就可以进行定制配置。
  • 将 coLinux 移植到 2.6 版本的 Linux 内核。我们撰写本文时,已经有用于 2.6 内核的 coLinux 内核补丁的开发发布版(development release)。2.6 版本的 Linux 内核具备很多可以在内核方面提高集群性能的特性,比如 O(1) 调度器和 I/O 调度器。
  • 增强 coLinux 内核驱动程序与 Windos 2000 和 XP 的兼容性 勿需多言,coLinux 和 Windows 内核之间还存在一些兼容性问题。(注意:coLinux 不支持 Windows 95/98/ME,这也是一个问题。)
  • 令 coLinux 使用宿主机器的 IP。到目前为止,coLinux 实例使用的是它自己的 IP地址。这样,在大规模的集群中会浪费大量 IP 地址。IPSec 隧道会有所帮助,它能够将全部客户网络数据封装到一个单独的 IPSec流中(同样,如 CosMos 的用法),不过 IPSec 本身增加了大量的延迟。另一个解决方案应该是 IP-over-IP隧道,这样可以避免加密的时间消耗,但是其实现需要付出更多努力。

相关项目
CosMos 是 Ian Latter所开发的一个项目,它的目标是提供一个具有紧凑文件系统的直接可用的 coLinux/openMosix 二进制程序。CosMos的一个非常好的特性是,它使用 IPSec 隧道来在集群节点间创建安全的端到端通信。(您可以通过 Ian.Latter@mq.edu.au 与Ian 联系。)

另一个项目(主要由 Christian Kauhaus 开发)的目标并不是 HPC,而是类似于著名的 Condor 项目,设计用于高吞吐率计算集群。与 CosMos 的共通之处是,其目标也是创建一个立即可用的程序包,不过在其他方面有所不同,比如:

  • 网络通信;出于性能原因,它没有使用 IPSec 隧道。
  • 配置服务器(Configuration Server);它的任务是管理配置,以及集群中非专用节点的加入与离开。

此项目仍处于早期 alpha 阶段 —— 观察它的发展应该会非常有趣。

原文转自:http://www.ltesting.net