关于CloudStack HA的设计原理和思路,在官方文档中已经给出了比较清晰的解释https://cwiki.apache.org/confluence/display/CLOUDSTACK/High+Availability+Developer%27s+Guide,这里不再赘述。
本文的主要目的是从代码的实现方面来梳理CS关于HA的逻辑。 重点是理清下图的细节:
我们先来看DirectAgentAttache的内部类PingTask,首先我们要知道每一个注册到CS中的主机都有一个对应的DirectAgentAttache,这也就意味着每一个HOST都有一个PingTask线程在后台循环运行,时间间隔是由全局变量ping.interval来指定的,默认是60s.
我们来看PingTask的代码
ServerResource resource = _resource;
if (resource != null) {
PingCommand cmd = resource.getCurrentStatus(_id);
int retried = 0;
while (cmd == null && ++retried <= _HostPingRetryCount.value()) {
Thread.sleep(1000*_HostPingRetryTimer.value());
cmd = resource.getCurrentStatus(_id);
}
if (cmd == null) {
s_logger.warn("Unable to get current status on " + _id + "(" + _name + ")");
return;
}
_agentMgr.handleCommands(DirectAgentAttache.this, seq, new Command[] {cmd});
}
_id代表host_id,当getCurrentStatus能返回正确的cmd就说明能够Ping通该host,那接下来就是执行_agentMgr.handleCommands
public void handleCommands(final AgentAttache attache, final long sequence, final Command[] cmds) {
for (final Pair<Integer, Listener> listener : _cmdMonitors) {
final boolean processed = listener.second().processCommands(attache.getId(), sequence, cmds);
}
}
其中我们关心BehindOnPingListener,我们来看它的processCommands方法
@Override
public boolean processCommands(final long agentId, final long seq, final Command[] commands) {
final boolean processed = false;
for (final Command cmd : commands) {
if (cmd instanceof PingCommand) {
pingBy(agentId);
}
}
return processed;
}
接下来是pingBy方法
public void pingBy(final long agentId) {
// Update PingMap with the latest time if