Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

DiscoverySeeds: hard coded instances to be discovered upon startup #1036

Merged
merged 1 commit into from
Dec 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ type Configuration struct {
DiscoveryQueueCapacity uint // Buffer size of the discovery queue. Should be greater than the number of DB instances being discovered
DiscoveryQueueMaxStatisticsSize int // The maximum number of individual secondly statistics taken of the discovery queue
DiscoveryCollectionRetentionSeconds uint // Number of seconds to retain the discovery collection information
DiscoverySeeds []string // Hard coded array of hostname:port, ensuring orchestrator discovers these hosts upon startup, assuming not already known to orchestrator
InstanceBulkOperationsWaitTimeoutSeconds uint // Time to wait on a single instance when doing bulk (many instances) operation
HostnameResolveMethod string // Method by which to "normalize" hostname ("none"/"default"/"cname")
MySQLHostnameResolveMethod string // Method by which to "normalize" hostname via MySQL server. ("none"/"@@hostname"/"@@report_host"; default "@@hostname")
Expand Down Expand Up @@ -320,6 +321,7 @@ func newConfiguration() *Configuration {
DiscoveryQueueCapacity: 100000,
DiscoveryQueueMaxStatisticsSize: 120,
DiscoveryCollectionRetentionSeconds: 120,
DiscoverySeeds: []string{},
InstanceBulkOperationsWaitTimeoutSeconds: 10,
HostnameResolveMethod: "default",
MySQLHostnameResolveMethod: "@@hostname",
Expand Down
9 changes: 9 additions & 0 deletions go/inst/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ type Instance struct {
Problems []string

LastDiscoveryLatency time.Duration

seed bool // Means we force this instance to be written to backend, even if it's invalid, empty or forgotten
}

// NewInstance creates a new, empty instance
Expand Down Expand Up @@ -221,6 +223,13 @@ func (this *Instance) IsOracleMySQL() bool {
return true
}

func (this *Instance) SetSeed() {
this.seed = true
}
func (this *Instance) IsSeed() bool {
return this.seed
}

// applyFlavorName
func (this *Instance) applyFlavorName() {
if this == nil {
Expand Down
28 changes: 21 additions & 7 deletions go/inst/instance_dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -1831,6 +1831,21 @@ func readUnseenMasterKeys() ([]InstanceKey, error) {
return res, nil
}

// InjectSeed: intented to be used to inject an instance upon startup, assuming it's not already known to orchestrator.
func InjectSeed(instanceKey *InstanceKey) error {
if instanceKey == nil {
return fmt.Errorf("InjectSeed: nil instanceKey")
}
clusterName := instanceKey.StringCode()
// minimal details:
instance := &Instance{Key: *instanceKey, Version: "Unknown", ClusterName: clusterName}
instance.SetSeed()
err := WriteInstance(instance, false, nil)
log.Debugf("InjectSeed: %+v, %+v", *instanceKey, err)
AuditOperation("inject-seed", instanceKey, "injected")
return err
}

// InjectUnseenMasters will review masters of instances that are known to be replicating, yet which are not listed
// in database_instance. Since their replicas are listed as replicating, we can assume that such masters actually do
// exist: we shall therefore inject them with minimal details into the database_instance table.
Expand Down Expand Up @@ -2470,21 +2485,20 @@ func mkInsertOdkuForInstances(instances []*Instance, instanceWasActuallyFound bo

// writeManyInstances stores instances in the orchestrator backend
func writeManyInstances(instances []*Instance, instanceWasActuallyFound bool, updateLastSeen bool) error {
if len(instances) == 0 {
return nil // nothing to write
}

writeInstances := [](*Instance){}
for _, instance := range instances {
if !InstanceIsForgotten(&instance.Key) {
writeInstances = append(writeInstances, instance)
if InstanceIsForgotten(&instance.Key) && !instance.IsSeed() {
continue
}
writeInstances = append(writeInstances, instance)
}
if len(writeInstances) == 0 {
return nil // nothing to write
}
sql, args, err := mkInsertOdkuForInstances(writeInstances, instanceWasActuallyFound, updateLastSeen)
if err != nil {
return err
}

if _, err := db.ExecOrchestrator(sql, args...); err != nil {
return err
}
Expand Down
16 changes: 16 additions & 0 deletions go/logic/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,19 @@ func SubmitMastersToKvStores(clusterName string, force bool) (kvPairs [](*kv.KVP
return kvPairs, submittedCount, log.Errore(selectedError)
}

func injectSeeds(seedOnce *sync.Once) {
seedOnce.Do(func() {
for _, seed := range config.Config.DiscoverySeeds {
instanceKey, err := inst.ParseRawInstanceKey(seed)
if err == nil {
inst.InjectSeed(instanceKey)
} else {
log.Errorf("Error parsing seed %s: %+v", seed, err)
}
}
})
}

// ContinuousDiscovery starts an asynchronuous infinite discovery process where instances are
// periodically investigated and their status captured, and long since unseen instances are
// purged and forgotten.
Expand Down Expand Up @@ -488,6 +501,8 @@ func ContinuousDiscovery() {
return time.Since(continuousDiscoveryStartTime) >= checkAndRecoverWaitPeriod
}

var seedOnce sync.Once

go ometrics.InitMetrics()
go ometrics.InitGraphiteMetrics()
go acceptSignals()
Expand Down Expand Up @@ -518,6 +533,7 @@ func ContinuousDiscovery() {
if IsLeaderOrActive() {
go inst.UpdateClusterAliases()
go inst.ExpireDowntime()
go injectSeeds(&seedOnce)
}
}()
case <-autoPseudoGTIDTick:
Expand Down