func NewSentinel(addr string) (d.Driver, error) { cli := redis.NewClient(&redis.Options{ Addr: addr, }) wk, abort := ctx.WithCancel(ctx.Background()) driver := &RedisDriver{ cli, abort, etcd.NewKeysAPI(disc.NewDiscovery()), } driver.follow(wk) return driver, nil }
func Register(service *Service) { alloc := AllocHelper(service.ProbeType) service.Key = make([]string, 0) serv := &srv{ service, etcd.NewKeysAPI(disc.NewDiscovery()), &etcd.SetOptions{TTL: service.TTL, PrevExist: etcd.PrevIgnore}, nil, } logger := log.WithFields(log.Fields{ "ID": serv.Id[:12], "srv": serv.Srv, "heartbeat": serv.Hb, "ttl": serv.TTL, }) // Advertise Key on the discovery service if serv.Port != "" { serv.Key = append(serv.Key, fmt.Sprintf("%s/%s:%s", serv.Srv, Advertise, serv.Port)) } else if len(serv.Net) > 0 { serv.Key = make([]string, 0) for _, p := range serv.Net { if p.PublicPort != 0 && p.IP == "0.0.0.0" { serv.Key = append(serv.Key, fmt.Sprintf("%s/%s:%d", serv.Srv, Advertise, p.PublicPort)) } } } var endpoint string if serv.ProbeEndpoint == "" { endpoint = path.Base(serv.Key[0]) } else { endpoint = path.Join(path.Base(serv.Key[0]), serv.ProbeEndpoint) } // TODO: setup driver for probing driver, drr := alloc(endpoint) if drr != nil { logger.WithFields(log.Fields{"err": drr}).Error("-register") return } serv.driver = driver logger.Debug("+register") wk, abort := ctx.WithCancel(RootContext) go func() { defer serv.driver.Close() // Request to establish proxy port to ambassador openProxyConfig(serv.ProxyCfg, serv.Proxy) // setup work cycle heartbeat, probe := time.NewTicker(serv.Hb), time.NewTicker(serv.PHb) defer func() { heartbeat.Stop() probe.Stop() }() logger.Info("start") func() { d, abort := ctx.WithTimeout(wk, UpkeepTimeout) if err := serv.keep(d); err != nil { logger.WithFields(log.Fields{"err": err, "state": serv.opts.PrevExist}).Error("-up") } else { logger.Info("+up") } abort() // release }() var chk = NewFail(MaxFailAttemps) for yay := true; yay; { select { case <-heartbeat.C: if !chk.Pass() { serv.urk() logger.Error("!up") } else { d, abort := ctx.WithTimeout(wk, UpkeepTimeout) if err := serv.keep(d); err != nil { logger.WithFields(log.Fields{"err": err, "state": serv.opts.PrevExist}).Error("-up") } else { logger.Info("+up") } abort() // release } case <-probe.C: d, abort := ctx.WithTimeout(wk, ProbeTimeout) if err := serv.probe(d); err != nil { count := chk.Bad() logger.WithFields(log.Fields{"err": err, "fail": count}).Warning("-probe") } else { chk.Good() logger.Debug("+probe") } abort() // release case <-wk.Done(): serv.down() logger.Warning("down") yay = false } } }() Record[serv.Id] = &RunningRecord{serv.Srv, abort} // register abort function for this service }