github.com/micro/go-micro/examples@v0.0.0-20210105173217-bf4ab679e18b/client/dc_selector/dc_selector.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/micro/go-micro/v2/client"
    11  	"github.com/micro/go-micro/v2/client/selector"
    12  	"github.com/micro/go-micro/v2/config/cmd"
    13  	"github.com/micro/go-micro/v2/registry"
    14  
    15  	example "github.com/micro/go-micro/examples/server/proto/example"
    16  )
    17  
    18  // Built in random hashed node selector
    19  type dcSelector struct {
    20  	opts selector.Options
    21  }
    22  
    23  var (
    24  	datacenter = "local"
    25  )
    26  
    27  func init() {
    28  	rand.Seed(time.Now().Unix())
    29  }
    30  
    31  func (n *dcSelector) Init(opts ...selector.Option) error {
    32  	for _, o := range opts {
    33  		o(&n.opts)
    34  	}
    35  	return nil
    36  }
    37  
    38  func (n *dcSelector) Options() selector.Options {
    39  	return n.opts
    40  }
    41  
    42  func (n *dcSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) {
    43  	services, err := n.opts.Registry.GetService(service)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	if len(services) == 0 {
    49  		return nil, selector.ErrNotFound
    50  	}
    51  
    52  	var nodes []*registry.Node
    53  
    54  	// Filter the nodes for datacenter
    55  	for _, service := range services {
    56  		for _, node := range service.Nodes {
    57  			if node.Metadata["datacenter"] == datacenter {
    58  				nodes = append(nodes, node)
    59  			}
    60  		}
    61  	}
    62  
    63  	if len(nodes) == 0 {
    64  		return nil, selector.ErrNotFound
    65  	}
    66  
    67  	var i int
    68  	var mtx sync.Mutex
    69  
    70  	return func() (*registry.Node, error) {
    71  		mtx.Lock()
    72  		defer mtx.Unlock()
    73  		i++
    74  		return nodes[i%len(nodes)], nil
    75  	}, nil
    76  }
    77  
    78  func (n *dcSelector) Mark(service string, node *registry.Node, err error) {
    79  	return
    80  }
    81  
    82  func (n *dcSelector) Reset(service string) {
    83  	return
    84  }
    85  
    86  func (n *dcSelector) Close() error {
    87  	return nil
    88  }
    89  
    90  func (n *dcSelector) String() string {
    91  	return "dc"
    92  }
    93  
    94  // Return a new first node selector
    95  func DCSelector(opts ...selector.Option) selector.Selector {
    96  	var sopts selector.Options
    97  	for _, opt := range opts {
    98  		opt(&sopts)
    99  	}
   100  	if sopts.Registry == nil {
   101  		sopts.Registry = registry.DefaultRegistry
   102  	}
   103  	return &dcSelector{sopts}
   104  }
   105  
   106  func call(i int) {
   107  	// Create new request to service go.micro.srv.example, method Example.Call
   108  	req := client.NewRequest("go.micro.srv.example", "Example.Call", &example.Request{
   109  		Name: "John",
   110  	})
   111  
   112  	rsp := &example.Response{}
   113  
   114  	// Call service
   115  	if err := client.Call(context.Background(), req, rsp); err != nil {
   116  		fmt.Println("call err: ", err, rsp)
   117  		return
   118  	}
   119  
   120  	fmt.Println("Call:", i, "rsp:", rsp.Msg)
   121  }
   122  
   123  func main() {
   124  	cmd.Init()
   125  
   126  	client.DefaultClient = client.NewClient(
   127  		client.Selector(DCSelector()),
   128  	)
   129  
   130  	fmt.Println("\n--- Call example ---")
   131  	for i := 0; i < 10; i++ {
   132  		call(i)
   133  	}
   134  }