From 5bcdf189ded3a14312e2618007786865ee88df2e Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 19 Dec 2018 00:57:16 +0300 Subject: [PATCH] implement some gossip options Signed-off-by: Vasiliy Tolstov --- registry/gossip/gossip.go | 51 ++++++++++++++++++++++++++++++-------- registry/gossip/options.go | 28 +++++++++++++++++++++ 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/registry/gossip/gossip.go b/registry/gossip/gossip.go index 99972a24..de2c66dd 100644 --- a/registry/gossip/gossip.go +++ b/registry/gossip/gossip.go @@ -2,9 +2,12 @@ package gossip import ( + "context" "encoding/json" "io/ioutil" + "net" "os" + "strconv" "strings" "sync" "time" @@ -12,7 +15,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/google/uuid" "github.com/hashicorp/memberlist" - "github.com/micro/go-log" + log "github.com/micro/go-log" "github.com/micro/go-micro/registry" pb "github.com/micro/go-micro/registry/gossip/proto" "github.com/mitchellh/hashstructure" @@ -56,7 +59,7 @@ type update struct { var ( // You should change this if using secure - DefaultSecret = []byte("gossip") + DefaultSecret = []byte("micro-gossip-key") // exactly 16 bytes ExpiryTick = time.Second * 5 ) @@ -104,14 +107,40 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { RetransmitMult: 3, } - // machine hostname - hostname, _ := os.Hostname() - // create a new default config c := memberlist.DefaultLocalConfig() - // set bind to random port - c.BindPort = 0 + if optConfig, ok := g.options.Context.Value(contextConfig{}).(*memberlist.Config); ok && optConfig != nil { + c = optConfig + } + + if hostport, ok := g.options.Context.Value(contextAddress{}).(string); ok { + host, port, err := net.SplitHostPort(hostport) + if err == nil { + pn, err := strconv.Atoi(port) + if err == nil { + c.BindPort = pn + } + c.BindAddr = host + } + } else { + // set bind to random port + c.BindPort = 0 + } + + if hostport, ok := g.options.Context.Value(contextAdvertise{}).(string); ok { + host, port, err := net.SplitHostPort(hostport) + if err == nil { + pn, err := strconv.Atoi(port) + if err == nil { + c.AdvertisePort = pn + } + c.AdvertiseAddr = host + } + } + + // machine hostname + hostname, _ := os.Hostname() // set the name c.Name = strings.Join([]string{"micro", hostname, uuid.New().String()}, "-") @@ -135,8 +164,6 @@ func configure(g *gossipRegistry, opts ...registry.Option) error { c.SecretKey = k } - // TODO: set advertise addr to advertise behind nat - // create the memberlist m, err := memberlist.Create(c) if err != nil { @@ -550,9 +577,13 @@ func NewRegistry(opts ...registry.Option) registry.Registry { watchers: make(map[string]chan *registry.Result), } + if gossip.options.Context == nil { + gossip.options.Context = context.Background() + } + // configure the gossiper if err := configure(gossip, opts...); err != nil { - log.Fatal("Error configuring registry: %v", err) + log.Fatalf("Error configuring registry: %v", err) } // run the updater diff --git a/registry/gossip/options.go b/registry/gossip/options.go index 26e8cd9f..cee50ee5 100644 --- a/registry/gossip/options.go +++ b/registry/gossip/options.go @@ -3,6 +3,7 @@ package gossip import ( "context" + "github.com/hashicorp/memberlist" "github.com/micro/go-micro/registry" ) @@ -15,3 +16,30 @@ func Secret(k []byte) registry.Option { o.Context = context.WithValue(o.Context, contextSecretKey{}, k) } } + +type contextAddress struct{} + +// Address to bind to - host:port +func Address(a string) registry.Option { + return func(o *registry.Options) { + o.Context = context.WithValue(o.Context, contextAddress{}, a) + } +} + +type contextConfig struct{} + +// Config allow to inject a *memberlist.Config struct for configuring gossip +func Config(c *memberlist.Config) registry.Option { + return func(o *registry.Options) { + o.Context = context.WithValue(o.Context, contextConfig{}, c) + } +} + +type contextAdvertise struct{} + +// The address to advertise for other gossip members - host:port +func Advertise(a string) registry.Option { + return func(o *registry.Options) { + o.Context = context.WithValue(o.Context, contextAdvertise{}, a) + } +}