gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/client/selector/dns/dns.go (about)

     1  // Package dns provides a dns SRV selector
     2  package dns
     3  
     4  import (
     5  	"fmt"
     6  	"net"
     7  	"strconv"
     8  
     9  	"gitee.com/liuxuezhan/go-micro-v1.18.0/client/selector"
    10  	"gitee.com/liuxuezhan/go-micro-v1.18.0/registry"
    11  )
    12  
    13  type dnsSelector struct {
    14  	options selector.Options
    15  	domain  string
    16  }
    17  
    18  var (
    19  	DefaultDomain = "local"
    20  )
    21  
    22  func (d *dnsSelector) Init(opts ...selector.Option) error {
    23  	for _, o := range opts {
    24  		o(&d.options)
    25  	}
    26  	return nil
    27  }
    28  
    29  func (d *dnsSelector) Options() selector.Options {
    30  	return d.options
    31  }
    32  
    33  func (d *dnsSelector) Select(service string, opts ...selector.SelectOption) (selector.Next, error) {
    34  	var srv []*net.SRV
    35  
    36  	// check if its host:port
    37  	host, port, err := net.SplitHostPort(service)
    38  	// not host:port
    39  	if err != nil {
    40  		// lookup the SRV record
    41  		_, srvs, err := net.LookupSRV(service, "tcp", d.domain)
    42  		if err != nil {
    43  			return nil, err
    44  		}
    45  		// set SRV records
    46  		srv = srvs
    47  		// got host:port
    48  	} else {
    49  		p, _ := strconv.Atoi(port)
    50  
    51  		// lookup the A record
    52  		ips, err := net.LookupHost(host)
    53  		if err != nil {
    54  			return nil, err
    55  		}
    56  
    57  		// create SRV records
    58  		for _, ip := range ips {
    59  			srv = append(srv, &net.SRV{
    60  				Target: ip,
    61  				Port:   uint16(p),
    62  			})
    63  		}
    64  	}
    65  
    66  	nodes := make([]*registry.Node, 0, len(srv))
    67  	for _, node := range srv {
    68  		nodes = append(nodes, &registry.Node{
    69  			Id:      node.Target,
    70  			Address: fmt.Sprintf("%s:%d", node.Target, node.Port),
    71  		})
    72  	}
    73  
    74  	services := []*registry.Service{
    75  		{
    76  			Name:  service,
    77  			Nodes: nodes,
    78  		},
    79  	}
    80  
    81  	sopts := selector.SelectOptions{
    82  		Strategy: d.options.Strategy,
    83  	}
    84  
    85  	for _, opt := range opts {
    86  		opt(&sopts)
    87  	}
    88  
    89  	// apply the filters
    90  	for _, filter := range sopts.Filters {
    91  		services = filter(services)
    92  	}
    93  
    94  	// if there's nothing left, return
    95  	if len(services) == 0 {
    96  		return nil, selector.ErrNoneAvailable
    97  	}
    98  
    99  	return sopts.Strategy(services), nil
   100  }
   101  
   102  func (d *dnsSelector) Mark(service string, node *registry.Node, err error) {}
   103  
   104  func (d *dnsSelector) Reset(service string) {}
   105  
   106  func (d *dnsSelector) Close() error {
   107  	return nil
   108  }
   109  
   110  func (d *dnsSelector) String() string {
   111  	return "dns"
   112  }
   113  
   114  func NewSelector(opts ...selector.Option) selector.Selector {
   115  	options := selector.Options{
   116  		Strategy: selector.Random,
   117  	}
   118  
   119  	for _, o := range opts {
   120  		o(&options)
   121  	}
   122  
   123  	return &dnsSelector{options: options, domain: DefaultDomain}
   124  }