func (d *delegate) LocalState(join bool) []byte {
	d.mtx.RLock()
	defer d.mtx.RUnlock()
	buf, _ := json.Marshal(d.data)
	return buf
}
LocalState is used for a TCP Push/Pull. This is sent to
the remote side in addition to the membership information. Any
data can be sent here. See MergeRemoteState as well. The `join`
boolean indicates this is for a join instead of a push/pull.
Implements memberlist.Delegate.
package cluster
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net"
	"strings"
	"sync"
	"time"
	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/log/level"
	"github.com/hashicorp/memberlist"
	"github.com/pborman/uuid"
)
type Config struct {
	ClusterHost   string
	ClusterPort   int
	AdvertiseHost string  
	AdvertisePort int     
	APIHost       string
	APIPort       int
	Type          string
	InitialPeers  []string
	Logger        log.Logger
}
type Peer struct {
	ml *memberlist.Memberlist
	d  *delegate
}
func NewPeer(config Config) (*Peer, error) {
	var (
		d = newDelegate(config.Logger)
		c = memberlist.DefaultLANConfig()
	)
	{
		c.Name = uuid.New()
		c.BindAddr = config.ClusterHost
		c.BindPort = config.ClusterPort
		c.AdvertiseAddr = config.AdvertiseHost
		c.AdvertisePort = config.AdvertisePort
		c.LogOutput = ioutil.Discard
		c.Delegate = d
		c.Events = d
	}
	ml, err := memberlist.Create(c)
	if err != nil {
		return nil, err
	}
	d.initialize(c.Name, config.Type, config.APIHost, config.APIPort, ml.NumMembers)
	n, _ := ml.Join(config.InitialPeers)
	level.Debug(config.Logger).Log("Join", n)
	return &Peer{
		ml: ml,
		d:  d,
	}, nil
}
func (p *Peer) Leave(timeout time.Duration) error {
	return p.ml.Leave(timeout)
}
func (p *Peer) Query(f func(peerType string) bool) (apiHostPorts []string) {
	for _, v := range p.d.query(f) {
		apiHostPort := net.JoinHostPort(v.APIHost, fmt.Sprint(v.APIPort))
		apiHostPorts = append(apiHostPorts, apiHostPort)
	}
	return apiHostPorts
}
type delegate struct {
	mtx    sync.RWMutex
	bcast  *memberlist.TransmitLimitedQueue
	data   map[string]peerInfo
	logger log.Logger
}
type peerInfo struct {
	Type    string `json:"type"`
	APIHost string `json:"api_host"`
	APIPort int    `json:"api_port"`
}
func newDelegate(logger log.Logger) *delegate {
	return &delegate{
		data:   map[string]peerInfo{},
		logger: logger,
	}
}
func (d *delegate) initialize(id string, peerType string, apiHost string, apiPort int, numNodes func() int) {
	d.mtx.Lock()
	defer d.mtx.Unlock()
	d.bcast = &memberlist.TransmitLimitedQueue{
		NumNodes:       numNodes,
		RetransmitMult: 3,
	}
	d.data[id] = peerInfo{peerType, apiHost, apiPort}
}
func (d *delegate) query(f func(peerType string) bool) map[string]peerInfo {
	res := map[string]peerInfo{}
	for k, info := range d.state() {
		if f(info.Type) {
			res[k] = info
		}
	}
	return res
}
func (d *delegate) state() map[string]peerInfo {
	d.mtx.RLock()
	defer d.mtx.RUnlock()
	res := map[string]peerInfo{}
	for k, v := range d.data {
		res[k] = v
	}
	return res
}
func (d *delegate) NodeMeta(limit int) []byte {
	d.mtx.RLock()
	defer d.mtx.RUnlock()
	return []byte{}  
}
func (d *delegate) NotifyMsg(b []byte) {
	if len(b) == 0 {
		return
	}
	var data map[string]peerInfo
	if err := json.Unmarshal(b, &data); err != nil {
		level.Error(d.logger).Log("method", "NotifyMsg", "b", strings.TrimSpace(string(b)), "err", err)
		return
	}
	d.mtx.Lock()
	defer d.mtx.Unlock()
	for k, v := range data {
		d.data[k] = v
	}
}
func (d *delegate) GetBroadcasts(overhead, limit int) [][]byte {
	d.mtx.RLock()
	defer d.mtx.RUnlock()
	if d.bcast == nil {
		panic("GetBroadcast before init")
	}
	return d.bcast.GetBroadcasts(overhead, limit)
}