orchestrator-client -c discover -i hostname:port
MySQLHostnameResolveMethod和HostnameResolveMethod
HostnameResolveMethod
func resolveHostname(hostname string) (string, error) {
switch strings.ToLower(config.Config.HostnameResolveMethod) {
case "none":
return hostname, nil
case "default":
return hostname, nil
case "cname":
return GetCNAME(hostname)
case "ip":
return getHostnameIP(hostname)
}
return hostname, nil
}
MySQLHostnameResolveMethod
...
db.QueryRow("select @@global.hostname, ifnull(@@global.report_host, ''), @@global.server_id, @@global.version, @@global.version_comment, @@global.read_only, @@global.binlog_format, @@global.log_bin, @@global.log_slave_updates").Scan(
&mysqlHostname, &mysqlReportHost, &instance.ServerID, &instance.Version, &instance.VersionComment, &instance.ReadOnly, &instance.Binlog_format, &instance.LogBinEnabled, &instance.LogReplicationUpdatesEnabled)
...
switch strings.ToLower(config.Config.MySQLHostnameResolveMethod) {
case "none":
resolvedHostname = instance.Key.Hostname
case "default", "hostname", "@@hostname":
resolvedHostname = mysqlHostname
case "report_host", "@@report_host":
if mysqlReportHost == "" {
err = fmt.Errorf("MySQLHostnameResolveMethod configured to use @@report_host but %+v has NULL/empty @@report_host", instanceKey)
goto Cleanup
}
resolvedHostname = mysqlReportHost
default:
resolvedHostname = instance.Key.Hostname
}
DiscoverByShowSlaveHosts
// 这里首先读取配置文件中的DiscoverByShowSlaveHosts配置,如果设置为True的话,进入下面的逻辑
if config.Config.DiscoverByShowSlaveHosts || isMaxScale {
// 这里去给定实例上发出一条SQL:show slave hosts,下面的事情就很简单了,就是做一些解析hostname之类的工作了
err := sqlutils.QueryRowsMap(db, `show slave hosts`,
func(m sqlutils.RowMap) error {
// MaxScale 1.1 may trigger an error with this command, but
// also we may see issues if anything on the MySQL server locks up.
// Consequently it's important to validate the values received look
// good prior to calling ResolveHostname()
host := m.GetString("Host")
port := m.GetIntD("Port", 0)
// 这里判断show slave hosts结果,如果host结果为空,则直接会返回失败
if host == "" || port == 0 {
if isMaxScale && host == "" && port == 0 {
// MaxScale reports a bad response sometimes so ignore it.
// - seen in 1.1.0 and 1.4.3.4
return nil
}
// otherwise report the error to the caller
return fmt.Errorf("ReadTopologyInstance(%+v) 'show slave hosts' returned row with <host,port>: <%v,%v>", instanceKey, host, port)
}
// 接下来,如果host不为空,那么会调用NewResolveInstanceKey(),该函数又吊用了newInstanceKey()这个函数,newInstanceKey()主要作用就是解析hostname,生成一个叫InstanceKey的结构体,内容为:instanceKye = &InstanceKey{Hostname: hostname, Port: port},最后return instanceKye,也就是对应下面的replicaKey这个变量
replicaKey, err := NewResolveInstanceKey(host, port)
if err == nil && replicaKey.IsValid() {
// 这个如果replicaKey有效,那么会进行正则匹配,规则就是配置文件中DiscoveryIgnoreReplicaHostnameFilters的配置,如果匹配到了会返回一个true,然而这里是!RegexpMatchPatterns,所以就是说匹配不到的话,会调用instance.AddReplicaKey(replicaKey)这个函数
if !RegexpMatchPatterns(replicaKey.StringCode(), config.Config.DiscoveryIgnoreReplicaHostnameFilters) {
instance.AddReplicaKey(replicaKey)
}
foundByShowSlaveHosts = true
}
return err
})
logReadTopologyInstanceError(instanceKey, "show slave hosts", err)
}
if !foundByShowSlaveHosts && !isMaxScale {
// Either not configured to read SHOW SLAVE HOSTS or nothing was there.
// Discover by information_schema.processlist
// 这里使用了协程,所以使用了wg
waitGroup.Add(1)
go func() {
defer waitGroup.Done()
// 对实例发出一个语句,就是查询processlist表,条件就是command IN ('Binlog Dump', 'Binlog Dump GTID')。后面基本和上面一样,只不过这个逻辑是通过processlist来发现拓补实例的
err := sqlutils.QueryRowsMap(db, `
select
substring_index(host, ':', 1) as slave_hostname
from
information_schema.processlist
where
command IN ('Binlog Dump', 'Binlog Dump GTID')
`,
func(m sqlutils.RowMap) error {
cname, resolveErr := ResolveHostname(m.GetString("slave_hostname"))
if resolveErr != nil {
logReadTopologyInstanceError(instanceKey, "ResolveHostname: processlist", resolveErr)
}
replicaKey := InstanceKey{Hostname: cname, Port: instance.Key.Port}
if !RegexpMatchPatterns(replicaKey.StringCode(), config.Config.DiscoveryIgnoreReplicaHostnameFilters) {
instance.AddReplicaKey(&replicaKey)
}
return err
})
logReadTopologyInstanceError(instanceKey, "processlist", err)
}()
}
结论
结语
文章转载自收获不止Oracle,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




