Esempio n. 1
0
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
}
Esempio n. 2
0
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
}