目标

ejabberd 集群的目标是能够使用多台服务器为单个域名或多个域名中的一小组域名提供服务,用于故障容错和可扩展性。

为构建可靠服务,支持大量用户,集群是必须具备功能。


工作方式

一个 XMPP 域名由一或多个 ejabberd 节点提供服务。这些节点可以运行在不同的机器上,它们之间通过网络连接。它们都必须能连接到所有其它节点的 4369 端口,并且有相同的 Magic Cookie(查看 Erlang/OTP 文档,换句话说,所有节点上的 ~ejabberd/.erlang.cookie 文件必须相同)。之所以如此,是因为所有节点会交换有关已连接用户、s2s 连接、已注册服务等信息。

每个 ejabberd 节点有如下模块:


Router

该模块是每个节点上 XMPP 数据包的主路由,它基于目的域名路由数据包。它使用全局路由表。在路由表中搜索数据包的目的域名,如果找到,那么将数据包路由到相应的进程,否则,将数据包发送到 s2s 管理器。


Local Router

该模块路由目的域名等于服务端的某个主机名的数据包。如果目的 JID 的用户部分非空,那么将数据包路由到会话管理器,否则,依据其内容,进行处理。


Session Manager

该模块将数据包路由到本地用户。它通过状态表(presence table)寻找数据包必须被发送到的用户资源。然后,数据包要么被路由到相应的 c2s 进程,要么被存储到离线存储中,要么被弹回。


s2s Manager

该模块将数据包路由到其它 XMPP 服务。它首先检查从数据包的源域名到数据包的目的域名的 s2s 连接是否存在。如果存在,那么 s2s 管理器将数据包路由到为该连接提供服务的进程,否则,打开新连接。


开始之前

在开始实现集群之前,需要考虑如下事宜:


集群设置

向集群中添加节点

假设已经在名为 ejabberd01 的节点上配置 ejabberd。接下来创建另一个节点(ejabberd02),并且将它们连接起来。

  1. /home/ejabberd/.erlang.cookie 文件从 ejabberd01 拷贝到 ejabberd02

或者给下面的所有 erl 命令传递 -setcookie <value> 选项

  1. 确保已正确配置新 ejabberd 节点。通常,新节点上的 ejabberd.yml 配置文件与其它集群节点的相同。

  2. 通过在相同网络内启动新 ejabberd 节点,并且在某个集群节点上,运行 join_cluster 的方式,向集群添加节点。比如,在 ejabberd02 节点上,因为已经启动 ejabberd,使用 ejabberdctl 脚本,以 ejabberd 用户的身份运行如下命令:

    这将启动所有节点间的内部复制,因此新节点可以开始从其它节点接收消息,并且被注册到路由表中。

从集群中移除节点

为从集群中移除节点,只需要关闭节点。对集群而言,确定节点是否正常运行没有指定的延迟,节点立即被从其它节点的路由条目中移除。所有直接连接到停止节点的客户端都将被断开,应该重新连接到其它节点。

如果在负载均衡后面使用集群,并且从负载均衡中将节点移除,那么新客户端不会再连接到该节点,但是已经建立的连接应该被保持。因此通过在大多数客户端自己断开连接后,停止节点的方式,可以平滑地移除节点。如果再次启动节点,那么立即将其添加回集群,直到显式地将其从集群中永久移除。

为从集群中永久移除正在运行的节点,必须在集群的某个节点上,以 ejabberd 用户的身份运行 leave_cluster 命令:

当调用 leave_cluster 永久移除节点时,节点必须正在运行。然后,它将立即停止。

重启集群节点

Ejabberd 社区版服务使用 mnesia 内部数据库管理集群和节点间同步。因此,只要至少有一个节点在运行,就可以重启 ejabberd 节点。如果停止集群中最后一个运行的节点,那么为恢复服务,必须先重启该节点。


参考文档