gitee.com/h79/goutils@v1.22.10/discovery/resolver/builder/builder.go (about)

     1  package builder
     2  
     3  import (
     4  	"gitee.com/h79/goutils/common/attributes"
     5  	"gitee.com/h79/goutils/common/random"
     6  	"sort"
     7  	"strings"
     8  )
     9  
    10  // Target
    11  //   - "dns://some_authority/foo.bar"
    12  //     Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"}
    13  type Target struct {
    14  	// "grpc", "thrift", "local"...
    15  	Type      string `json:"type"`
    16  	Scheme    string `json:"scheme"`
    17  	Authority string `json:"authority"`
    18  	Endpoint  string `json:"endpoint"`
    19  }
    20  
    21  const KDefBuild = "/"
    22  
    23  func (target *Target) SchemeWith(build string) string {
    24  	addr := ""
    25  	if len(build) == 0 {
    26  		build = KDefBuild
    27  	}
    28  	if len(target.Scheme) > 0 {
    29  		addr = target.Scheme + "://"
    30  	}
    31  	if len(target.Authority) > 0 {
    32  		addr += target.Authority
    33  	}
    34  	if len(target.Endpoint) > 0 {
    35  		if len(addr) > 0 {
    36  			addr += build
    37  		}
    38  		addr += target.Endpoint
    39  	}
    40  	return addr
    41  }
    42  
    43  func (target *Target) NameWith(build string) string {
    44  	addr := ""
    45  	if len(build) == 0 {
    46  		build = KDefBuild
    47  	}
    48  	if len(target.Authority) > 0 {
    49  		addr += target.Authority
    50  	}
    51  	if len(target.Endpoint) > 0 {
    52  		if len(addr) > 0 {
    53  			addr += build
    54  		}
    55  		addr += target.Endpoint
    56  	}
    57  	return addr
    58  }
    59  
    60  func TargetWithGrpc(scheme, authority, endpoint string) Target {
    61  	return TargetWith("grpc", scheme, authority, endpoint)
    62  }
    63  
    64  func TargetWithThrift(scheme, authority, endpoint string) Target {
    65  	return TargetWith("thrift", scheme, authority, endpoint)
    66  }
    67  
    68  func TargetWithLocal(scheme, authority, endpoint string) Target {
    69  	return TargetWith("local", scheme, authority, endpoint)
    70  }
    71  
    72  func TargetWith(ty, scheme, authority, endpoint string) Target {
    73  	return Target{
    74  		Type:      ty,
    75  		Scheme:    scheme,
    76  		Authority: authority,
    77  		Endpoint:  endpoint,
    78  	}
    79  }
    80  
    81  // split2 returns the values from strings.SplitN(s, sep, 2).
    82  // If sep is not found, it returns ("", "", false) instead.
    83  func split2(s, sep string) (string, string, bool) {
    84  	spl := strings.SplitN(s, sep, 2)
    85  	if len(spl) < 2 {
    86  		return "", "", false
    87  	}
    88  	return spl[0], spl[1], true
    89  }
    90  
    91  // ParseTarget splits target into a resolver.Target struct containing scheme,
    92  // authority and endpoint.
    93  //
    94  // If target is not a valid scheme://authority/endpoint, it returns {Endpoint:
    95  // target}.
    96  func ParseTarget(target string) (ret Target) {
    97  	var ok bool
    98  	ret.Scheme, ret.Endpoint, ok = split2(target, "://")
    99  	if !ok {
   100  		return Target{Endpoint: target}
   101  	}
   102  	ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, KDefBuild)
   103  	if !ok {
   104  		return Target{Endpoint: target}
   105  	}
   106  	return ret
   107  }
   108  
   109  // Builder creates a resolver that will be used to watch name resolution updates.
   110  type Builder interface {
   111  	// Build creates a new resolver for the given target.
   112  	//
   113  	// gRPC dial calls Build synchronously, and fails if the returned error is
   114  	// not nil.
   115  	Build(target Target, cc Connector) (Resolver, error)
   116  
   117  	// Scheme returns the scheme supported by this resolver.
   118  	Scheme() string
   119  
   120  	Type() string
   121  }
   122  
   123  // Resolver watches for the updates on the specified target.
   124  // Updates include address updates and service config updates.
   125  type Resolver interface {
   126  	// ResolveNow will be called by gRPC to try to resolve the target name
   127  	// again. It's just a hint, resolver can ignore this if it's not necessary.
   128  	//
   129  	// It could be called multiple times concurrently.
   130  	ResolveNow()
   131  
   132  	// Close closes the resolver.
   133  	Close()
   134  }
   135  
   136  type Connector interface {
   137  	// UpdateState updates the state of the ClientConn appropriately.
   138  	UpdateState(State)
   139  
   140  	// ReportError notifies the ClientConn that the Resolver encountered an
   141  	// error.  The ClientConn will notify the load balancer and begin calling
   142  	// ResolveNow on the Resolver with exponential backoff.
   143  	ReportError(error)
   144  }
   145  
   146  // Address Notice: This type is EXPERIMENTAL and may be changed or removed in a
   147  // later release.
   148  type Address struct {
   149  	// Addr is the server address on which a connection will be established.
   150  	Addr string
   151  
   152  	// ServerName is the name of this address.
   153  	// If non-empty, the ServerName is used as the transport certification authority for
   154  	// the address, instead of the hostname from the Dial target string. In most cases,
   155  	// this should not be set.
   156  	//
   157  	// If Method is GRPCLB, ServerName should be the name of the remote load
   158  	// balancer, not the name of the backend.
   159  	//
   160  	// WARNING: ServerName must only be populated with trusted values. It
   161  	// is insecure to populate it with data from untrusted inputs since untrusted
   162  	// values could be used to bypass the authority checks performed by TLS.
   163  	ServerName string
   164  
   165  	// Attributes contains arbitrary data about this address intended for
   166  	// consumption by the load balancing policy.
   167  	Attributes *attributes.Attributes
   168  
   169  	// Weight sort max in front
   170  	Weight int64
   171  }
   172  
   173  // State contains the current Resolver state relevant to the ClientConn.
   174  type State struct {
   175  	// Addresses is the latest set of resolved addresses for the target.
   176  	Addresses Addresses
   177  
   178  	// Attributes contains arbitrary data about the resolver intended for
   179  	// consumption by the load balancing policy.
   180  	Attributes *attributes.Attributes
   181  }
   182  
   183  type Addresses []Address
   184  
   185  func (a Addresses) Len() int {
   186  	return len(a)
   187  }
   188  
   189  func (a Addresses) Swap(i, j int) {
   190  	a[i], a[j] = a[j], a[i]
   191  }
   192  
   193  // Less 权重大的在前面
   194  func (a Addresses) Less(i, j int) bool {
   195  	return a[i].Weight >= a[j].Weight
   196  }
   197  
   198  func (a Addresses) ToWeight() {
   199  	r := random.Random()
   200  	for index, _ := range a {
   201  		a[index].Weight = r.Int63n(1000)
   202  	}
   203  	sort.Sort(a)
   204  }