逆熵(anti-entropy) 指的是 agent 本地定期向 consul server 同步信息,以及拉取 consul server 中的信息然后合并的过程。
熵是系统变得越来越无序的趋势。consul 的逆熵机制旨在对抗这种趋势,即使在组件发生故障的情况下也能保持集群的有序状态。
有两个关键概念需要区分:
agent - 即 consul agent,agent 中的信息由 consul client 自己维护。
catalog - 是集群中所有 agent 中信息的抽象。catalog 中的信息由 consul servers 进行维护。
比如
http://10.41.12.170:8500/v1/agent/service/wax-delivery
得到的是注册在10.41.12.170
上服务名为 wax-delivery 的节点(1个);而
curl http://10.41.12.170:8500/v1/catalog/service/wax-delivery
得到的是整个集群中服务名为 wax-delivery 的节点(36个)。即当使用
/v1/agent
路径时,agent 会进行本地处理,然后把处理结果同步给 consul server;而当使用/v1/catalog
路径时,agent 会将请求转发给 consul server,由 consul server 进行处理。换句话说,即使在某一个 consul client 所在的 agent 请求
/v1/catalog/register
注册某 A 服务,也不会在该 agent 的/v1/agent/services
响应中包含 A 服务。
例如,当用户向 agent 注册新服务时,agent 会通知 catalog 更改。类似地,当从 agent 中注销服务时,也会同步给 catalog。
注意,agent 中的信息具有权威性。即当 agent 拉取到 server 中的信息和本地不同时,以 agent 为准。
实现
在 agent 启动时,会开始进行同步任务:
cmd/agent/agent.go
func (a *Agent) Start(ctx context.Context) error {
// ...
a.State = local.NewState(LocalConfig(c), a.logger, a.tokens)
// c.AEInterval consul 内部写死 1 分钟。
a.sync = ae.NewStateSyncer(a.State, c.AEInterval, a.shutdownCh, a.logger)
// ...
// Setup either the client or the server.
if c.ServerMode {
server, err := consul.NewServer(consulCfg, options...)
if err != nil {
return fmt.Errorf("Failed to start Consul server: %v", err)
}
a.delegate = server
} else {
client, err := consul.NewClient(consulCfg, options...)
if err != nil {
return fmt.Errorf("Failed to start Consul client: %v", err)
}
a.delegate = client
}
// the staggering of the state syncing depends on the cluster size.
a.sync.ClusterSize = func() int {
return len(a.delegate.LANMembers()) }
// ...
}
其中 a.State
实现了如下的 SyncState 接口
,即 a.sync
的数据存储为 a.State
,并通过 SyncState 接口
提供的方法进行同步操作。
type</