现在es的集群发现用的是unicast模式,所以要将新节点加入集群,需要配置unicast节点地址列表,也就是discovery.zen.ping.unicast.hosts
,默认值是本机,除非要将集群部署在同一台机器上,否则必须配置。
下面进入源码看一下读取unicast节点列表的具体过程。
入口在UnicastZenPing
类的下面这个方法里面:
/**
* a variant of {@link #ping(Consumer, TimeValue)}, but allows separating the scheduling duration
* from the duration used for request level time outs. This is useful for testing
*/
protected void ping(final Consumer<PingCollection> resultsConsumer,
final TimeValue scheduleDuration,
final TimeValue requestDuration) {
final List<TransportAddress> seedAddresses = new ArrayList<>();
seedAddresses.addAll(hostsProvider.buildDynamicHosts(createHostsResolver()));
...
}
新启动的节点要ping(关于ping,会在《elasticsearch源码:ping的发送与处理过程》中讨论)集群内的其它节点,所以要构造节点地址列表,即上面代码里的seedAddresses
。
然后debug一路跟踪会进入SettingsBasedHostsProvider
类的buildDynamicHosts
方法:
@Override
public List<TransportAddress> buildDynamicHosts(HostsResolver hostsResolver) {
return hostsResolver.resolveHosts(configuredHosts, limitPortCounts);
}
这里调用传入的HostsResolver
根据configuredHosts
和limitPortCounts
参数解析出unicast节点列表。
这两个参数在SettingsBasedHostsProvider
类的构造函数里面设置:
public SettingsBasedHostsProvider(Settings settings, TransportService transportService) {
super(settings);
if (DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.exists(settings)) {
configuredHosts = DISCOVERY_ZEN_PING_UNICAST_HOSTS_SETTING.get(settings);
// we only limit to 1 address, makes no sense to ping 100 ports
limitPortCounts = LIMIT_FOREIGN_PORTS_COUNT;
} else {
// if unicast hosts are not specified, fill with simple defaults on the local machine
configuredHosts = transportService.getLocalAddresses();
limitPortCounts = LIMIT_LOCAL_PORTS_COUNT;
}
logger.debug("using initial hosts {}", configuredHosts);
}
这里用到了discovery.zen.ping.unicast.hosts
配置,elasticsearch.yml
文件的所有配置都会被封装到Settings
类。可以看到,如果有这个配置,则用配置的值,limitPortCounts值为1;如果没有,则用默认的本机地址,即"127.0.0.1"和"[::1]",limitPortCounts值为5。
具体解析过程在TcpTransport
类的addressesFromString
方法:
@Override
public TransportAddress[] addressesFromString(String address, int perAddressLimit) throws UnknownHostException {
return parse(address, settings.get("transport.profiles.default.port", PORT.get(settings)), perAddressLimit);
}
这里调用parse
方法来做最后的解析,传入的参数address
即为discovery.zen.ping.unicast.hosts
值。
parse
方法较长,就不罗列了,自行下载源码点进去一看便知,只做如下总结:
- elasticsearch集群发现采用
unicast
模式; unicast
的地址列表通过discovery.zen.ping.unicast.hosts
来配置;discovery.zen.ping.unicast.hosts
可以配置为[“127.0.0.1”, “127.0.0.1:9301”,"[::1]"]的形式;- 如果
discovery.zen.ping.unicast.hosts
中没有配置端口,会从transport.profiles.default.port
配置读取,可以配置单个值,也可以配置为范围,如“9300-9400”; - 如果没有配置
transport.profiles.default.port
,将会读取transport.tcp.port
配置作为端口,一样可以是单个值也可以是范围; - 如果
transport.tcp.port
也没有配置,将会使用默认值“9300-9400”,是一个范围; - 对于配置了
discovery.zen.ping.unicast.hosts
的情况,elasticsearch代码中写死了限制端口个数为1个,所以如果port的值为一个范围,则取第一个端口,即端口配置“9300-9400”实际等同于“9300”(所以端口配置成范围是没有意义的); - 对于没有配置
discovery.zen.ping.unicast.hosts
的情况(也就是本机),elasticsearch代码中写死了限制端口个数为5个,所以如果port的值为一个范围,则取前5个端口。