uWSGI Legion子系统¶
自uWSGI 1.9-dev起,已经添加了一个用于集群的新的子系统:Legion子系统。一个Legion是一组不断争取主导的uWSGI节点。每个节点都有一个武力值 (如果可能的话,彼此间该值不同)。具有最高武力值的节点就是这个Legion的Lord (或者如果你喜欢不大游戏的说法,嗯,更工程师点的术语是:master)。这种不断的斗争会生成7种事件:
setup
- legion子系统在一个节点上启动的时候join
- 在第一次到达仲裁时,只有在新加入的节点上lord
- 当该节点成为lordunlord
- 当这个节点失去了lord称号death
- 当legion子系统关闭的时候node-joined
- 当任何新节点加入到我们的legion的时候node-left
- 当任何节点离开我们的legion的时候
每当这样的一个事件发生的时候,你都可以触发操作。
注意:要构建带Legion支持的uWSGI,则必须安装 openssl
头文件。
IP接管¶
这对于集群环境来说,是一个非常常见的配置。IP地址是一种必须只由一个节点拥有的资源。对于这个例子而言,那个节点就是我们的Lord。如果我们正确的配置了一个Legion (记住,一个uWSGI实例可以是所有你需要的legion的成员),那么我们可以很容易实现IP接管。
[uwsgi]
legion = clusterip 225.1.1.1:4242 98 bf-cbc:hello
legion-node = clusterip 225.1.1.1:4242
legion-lord = clusterip cmd:ip addr add 192.168.173.111/24 dev eth0
legion-lord = clusterip cmd:arping -c 3 -S 192.168.173.111 192.168.173.1
legion-setup = clusterip cmd:ip addr del 192.168.173.111/24 dev eth0
legion-unlord = clusterip cmd:ip addr del 192.168.173.111/24 dev eth0
legion-death = clusterip cmd:ip addr del 192.168.173.111/24 dev eth0
在这个例子中,我们加入了一个名为 clusterip
的legion。要从其他节点接收消息,那么绑定到多播地址225.1.1.1:4242。这个节点的武力值会是98,而每一条消息将会使用CBC中的Blowfish算法,使用共享密钥 hello
进行加密。 legion-node
选项制定了我们宣布消息的目的地。由于我们使用多播,因此只需要制定一个单一的“节点”。最后的选项是在该集群的不同阶段触发的动作。对于一个IP接管解决方案,我们简单依赖于Linux的 iproute
命令来设置/取消设置ip地址,发送一个额外的ARP消息来宣告这种改变。显然,这个特定的例子需要root选项,或者 CAP_NET_ADMIN
Linux能力。因此,确保不要在与管理IP接管相同的uWSGI实例上运行不可信应用。
仲裁集¶
要选择一个Lord,Legion中的每个成员都要进行投票。当一个legion中所有活动成员都同意选择一个Lord的时候,那么这个Lord就会当选,而老的Lord会被降级。每当加入一个新的节点,或者有节点离开的时候,就会重新计算仲裁集,然后被记录到整个集群中。
选择Lord¶
一般来讲,具有较高武力值的节点会被选为Lord,但是可能会出现多个节点具有相同武力值的情况。当启动一个节点的时候,会给它分配一个UUID。如果两个节点具有相同的武力值,那么拥有较高字典序的UUID值的那个节点将会胜出。
分裂的集群¶
虽然Legion中的每个成员必须发送它内部集群成员的校验和,但是系统仍然易受“分裂的集群”问题的攻击。如果一个节点失去了与集群的连接,那么它可能会相信它是唯一可用的节点,然后开始Lord模式。
对于许多场景来说,这并不是最佳的。如果在一个legion中有超过2个节点,那么你可能想要考虑调整仲裁集水平。仲裁集水平是选举一个lord所需的票数(与节点数相对)。
legion-quorum
是用于这项任务的选项。你可以通过让Legion子系统检查至少2票来解决分裂集群问题:
[uwsgi]
legion = clusterip 225.1.1.1:4242 98 bf-cbc:hello
legion-node = clusterip 225.1.1.1:4242
legion-quorum = clusterip 2
legion-lord = clusterip cmd:ip addr add 192.168.173.111/24 dev eth0
legion-lord = clusterip cmd:arping -c 3 -S 192.168.173.111 192.168.173.1
legion-setup = clusterip cmd:ip addr del 192.168.173.111/24 dev eth0
legion-unlord = clusterip cmd:ip addr del 192.168.173.111/24 dev eth0
legion-death = clusterip cmd:ip addr del 192.168.173.111/24 dev eth0
由1.9.7开始,你可以使用武力值为0的节点 (概念类似于MongoDB的 Arbiter节点),在检查仲裁集的时候会考虑这样的节点,但是这样的节点将永远不会成为Lord。这在你只需要一对节点,但是要对抗分裂集群的时候很有用。
动作¶
一个legion的四个阶段都能触发动作。动作系统是模块化的,因此你可以添加新类型的动作。目前支持的动作是:
cmd:<command>
¶
运行一个shell命令。
signal:<num>
¶
引发一个uWSGI信号。
log:<msg>
¶
记录一个消息。例如,你可以将日志动作与告警系统结合在一起,从而获得免费的集群监控。
Multicast, broadcast and unicast
¶
即使多播可能是实现集群最简单的方式,但是它不是适用于所有网络的。如果多播不可选,那么你可以依赖于正常的IP地址。仅需绑定到一个地址上,然后发送所有你需要的legion-node选项:
[uwsgi]
legion = mycluster 192.168.173.17:4242 98 bf-cbc:hello
legion-node = mycluster 192.168.173.22:4242
legion-node = mycluster 192.168.173.30:4242
legion-node = mycluster 192.168.173.5:4242
这是用于一个拥有4个节点的集群(这个节点 + 3个其他节点)
多Legion¶
你可以把多个legion加入到相同的实例中。只是要记住,为每个legion使用不同的地址 (多播情况下则是端口)。
[uwsgi]
legion = mycluster 192.168.173.17:4242 98 bf-cbc:hello
legion-node = mycluster 192.168.173.22:4242
legion-node = mycluster 192.168.173.30:4242
legion-node = mycluster 192.168.173.5:4242
legion = mycluster2 225.1.1.1:4243 99 aes-128-cbc:secret
legion-node = mycluster2 225.1.1.1:4243
legion = anothercluster 225.1.1.1:4244 91 aes-256-cbc:secret2
legion-node = anothercluster 225.1.1.1:4244
安全性¶
Legion子系统发送的每个包都是使用特定的加密方法,一个预先共享的密钥以及一个可选的IV(初始化向量)进行加密的。取决于加密方法,IV可能是一个必要参数。要获取支持的加密方法列表,运行 openssl enc -h
。
重要
Legion的每个节点必须使用相同的加密参数。
要指定IV,仅需添加另一个参数到 legion 选项。
[uwsgi]
legion = mycluster 192.168.173.17:4242 98 bf-cbc:hello thisistheiv
legion-node = mycluster 192.168.173.22:4242
legion-node = mycluster 192.168.173.30:4242
legion-node = mycluster 192.168.173.5:4242
要减少基于重放攻击的影响,拒绝带低于30秒的时间戳的包。这是一个可调参数。如果你对所有节点的时间无法控制,那么你可以增加时钟偏差公差。
调整和时间偏差¶
当前,你可以调整三个参数。这些调整项影响系统中的所有Legion。每个包发送的频率 (以秒为单位) (legion-freq <secs>),节点不发送包后经过多少时间会被认为已经死亡(该时间以秒为单位) (legion-tolerance <secs>),以及节点之间的时间偏差数 (legion-skew-tolerance <secs>)。Legion子系统要求严格的时间同步,因此强烈建议使用NTP或者类似的工具。默认情况下,每3秒发送每个包,一个节点会在(不发送包后经过)15秒后认为死亡,而允许30秒的时间偏差。减少偏差容忍度应该加大对重放工具的安全保护。
Lord scroll (即将推出)¶
Legion子系统可以用于各种各样的目的,从master选举到节点自动发现或者简单的监控。一个例子是将”一组数据” (一个scroll)赋给每个节点。这个的一种使用时传递重新配置的参数给你的应用,或者记录特定的消息。目前,scroll系统正在加以改进之中,因此,如果你有任何想法,那么请加入到我们的邮件列表或者IRC频道中吧。
Legion API¶
你可以通过简单调用以下函数来判断实例是否是Legion的Lord:
int uwsgi_legion_i_am_the_lord(char *legion_name);
如果当前实例时特定Legion的Lord的话,则返回1。
- Python插件将其公开为
uwsgi.i_am_the_lord(name)
- PSGI插件将其公开为
uwsgi::i_am_the_lord(name)
- Rack插件将其公开为
UWSGI::i_am_the_lord(name)
显然,未来将会添加更多的API函数,你可以自由公开你的想法。
统计信息¶
可以在 uWSGI Stats服务器 中找到Legion的信息。确保理解“节点”和“成员”之间的不同。节点是你用 legion-node 选项配置的对端,而成员是加入到集群的有效的节点。
老的集群子系统¶
在0.9开发周期中,添加了一个集群子系统 (基于多播)。它非常原始不可靠,并且很有可能没人把它当回事。新的方法是使用可以使用不同后端的一般的API来改变它。Legion子系统可以是这些后端中的一员,以及像corosync或者redhat集群套件这样的项目(也可以是这些后端)。