func NewGRPC17Health(
	eps []string,
	timeout time.Duration,
	dialFunc DialFunc,
) *GRPC17Health {
	notifyCh := make(chan []grpc.Address)
	addrs := eps2addrs(eps)
	hb := &GRPC17Health{
		addrs:              addrs,
		eps:                eps,
		notifyCh:           notifyCh,
		readyc:             make(chan struct{}),
		healthCheck:        func(ep string) (bool, error) { return grpcHealthCheck(ep, dialFunc) },
		unhealthyHostPorts: make(map[string]time.Time),
		upc:                make(chan struct{}),
		stopc:              make(chan struct{}),
		downc:              make(chan struct{}),
		donec:              make(chan struct{}),
		updateAddrsC:       make(chan NotifyMsg),
		hostPort2ep:        getHostPort2ep(eps),
	}
	if timeout < minHealthRetryDuration {
		timeout = minHealthRetryDuration
	}
	hb.healthCheckTimeout = timeout

	close(hb.downc)
	go hb.updateNotifyLoop()
	hb.wg.Add(1)
	go func() {
		defer hb.wg.Done()
		hb.updateUnhealthy()
	}()
	return hb
}
func NewGRPC17Health(
	eps []string,
	timeout time.Duration,
	dialFunc DialFunc,
) *GRPC17Health {
	notifyCh := make(chan []grpc.Address)
	addrs := eps2addrs(eps)
	hb := &GRPC17Health{
		addrs:              addrs,
		eps:                eps,
		notifyCh:           notifyCh,
		readyc:             make(chan struct{}),
		healthCheck:        func(ep string) (bool, error) { return grpcHealthCheck(ep, dialFunc) },
		unhealthyHostPorts: make(map[string]time.Time),
		upc:                make(chan struct{}),
		stopc:              make(chan struct{}),
		downc:              make(chan struct{}),
		donec:              make(chan struct{}),
		updateAddrsC:       make(chan NotifyMsg),
		hostPort2ep:        getHostPort2ep(eps),
	}
	if timeout < minHealthRetryDuration {
		timeout = minHealthRetryDuration
	}
	hb.healthCheckTimeout = timeout

	close(hb.downc)
	go hb.updateNotifyLoop()
	hb.wg.Add(1)
	go func() {
		defer hb.wg.Done()
		hb.updateUnhealthy()
	}()
	return hb
}
// NewGRPC17Health returns a new health balancer with gRPC v1.7.