1package etcdv3 2 3import ( 4 "context" 5 "io" 6 "time" 7 8 "github.com/go-kit/kit/endpoint" 9 "github.com/go-kit/kit/log" 10 "github.com/go-kit/kit/sd" 11 "github.com/go-kit/kit/sd/lb" 12) 13 14func Example() { 15 // Let's say this is a service that means to register itself. 16 // First, we will set up some context. 17 var ( 18 etcdServer = "10.0.0.1:2379" // in the change from v2 to v3, the schema is no longer necessary if connecting directly to an etcd v3 instance 19 prefix = "/services/foosvc/" // known at compile time 20 instance = "1.2.3.4:8080" // taken from runtime or platform, somehow 21 key = prefix + instance // should be globally unique 22 value = "http://" + instance // based on our transport 23 ctx = context.Background() 24 ) 25 26 options := ClientOptions{ 27 // Path to trusted ca file 28 CACert: "", 29 30 // Path to certificate 31 Cert: "", 32 33 // Path to private key 34 Key: "", 35 36 // Username if required 37 Username: "", 38 39 // Password if required 40 Password: "", 41 42 // If DialTimeout is 0, it defaults to 3s 43 DialTimeout: time.Second * 3, 44 45 // If DialKeepAlive is 0, it defaults to 3s 46 DialKeepAlive: time.Second * 3, 47 } 48 49 // Build the client. 50 client, err := NewClient(ctx, []string{etcdServer}, options) 51 if err != nil { 52 panic(err) 53 } 54 55 // Build the registrar. 56 registrar := NewRegistrar(client, Service{ 57 Key: key, 58 Value: value, 59 }, log.NewNopLogger()) 60 61 // Register our instance. 62 registrar.Register() 63 64 // At the end of our service lifecycle, for example at the end of func main, 65 // we should make sure to deregister ourselves. This is important! Don't 66 // accidentally skip this step by invoking a log.Fatal or os.Exit in the 67 // interim, which bypasses the defer stack. 68 defer registrar.Deregister() 69 70 // It's likely that we'll also want to connect to other services and call 71 // their methods. We can build an Instancer to listen for changes from etcd, 72 // create Endpointer, wrap it with a load-balancer to pick a single 73 // endpoint, and finally wrap it with a retry strategy to get something that 74 // can be used as an endpoint directly. 75 barPrefix := "/services/barsvc" 76 logger := log.NewNopLogger() 77 instancer, err := NewInstancer(client, barPrefix, logger) 78 if err != nil { 79 panic(err) 80 } 81 endpointer := sd.NewEndpointer(instancer, barFactory, logger) 82 balancer := lb.NewRoundRobin(endpointer) 83 retry := lb.Retry(3, 3*time.Second, balancer) 84 85 // And now retry can be used like any other endpoint. 86 req := struct{}{} 87 if _, err = retry(ctx, req); err != nil { 88 panic(err) 89 } 90} 91 92func barFactory(string) (endpoint.Endpoint, io.Closer, error) { return endpoint.Nop, nil, nil } 93