dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/balancer/clusterresolver/config.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  /*
    19   *
    20   * Copyright 2021 gRPC authors.
    21   *
    22   */
    23  
    24  package clusterresolver
    25  
    26  import (
    27  	"bytes"
    28  	"encoding/json"
    29  	"fmt"
    30  	"strings"
    31  )
    32  
    33  import (
    34  	"google.golang.org/grpc/balancer/roundrobin"
    35  
    36  	"google.golang.org/grpc/serviceconfig"
    37  )
    38  
    39  import (
    40  	"dubbo.apache.org/dubbo-go/v3/xds/balancer/ringhash"
    41  	internalserviceconfig "dubbo.apache.org/dubbo-go/v3/xds/utils/serviceconfig"
    42  )
    43  
    44  // DiscoveryMechanismType is the type of discovery mechanism.
    45  type DiscoveryMechanismType int
    46  
    47  const (
    48  	// DiscoveryMechanismTypeEDS is eds.
    49  	DiscoveryMechanismTypeEDS DiscoveryMechanismType = iota // `json:"EDS"`
    50  	// DiscoveryMechanismTypeLogicalDNS is DNS.
    51  	DiscoveryMechanismTypeLogicalDNS // `json:"LOGICAL_DNS"`
    52  )
    53  
    54  // MarshalJSON marshals a DiscoveryMechanismType to a quoted json string.
    55  //
    56  // This is necessary to handle enum (as strings) from JSON.
    57  //
    58  // Note that this needs to be defined on the type not pointer, otherwise the
    59  // variables of this type will marshal to int not string.
    60  func (t DiscoveryMechanismType) MarshalJSON() ([]byte, error) {
    61  	buffer := bytes.NewBufferString(`"`)
    62  	switch t {
    63  	case DiscoveryMechanismTypeEDS:
    64  		buffer.WriteString("EDS")
    65  	case DiscoveryMechanismTypeLogicalDNS:
    66  		buffer.WriteString("LOGICAL_DNS")
    67  	}
    68  	buffer.WriteString(`"`)
    69  	return buffer.Bytes(), nil
    70  }
    71  
    72  // UnmarshalJSON unmarshals a quoted json string to the DiscoveryMechanismType.
    73  func (t *DiscoveryMechanismType) UnmarshalJSON(b []byte) error {
    74  	var s string
    75  	err := json.Unmarshal(b, &s)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	switch s {
    80  	case "EDS":
    81  		*t = DiscoveryMechanismTypeEDS
    82  	case "LOGICAL_DNS":
    83  		*t = DiscoveryMechanismTypeLogicalDNS
    84  	default:
    85  		return fmt.Errorf("unable to unmarshal string %q to type DiscoveryMechanismType", s)
    86  	}
    87  	return nil
    88  }
    89  
    90  // DiscoveryMechanism is the discovery mechanism, can be either EDS or DNS.
    91  //
    92  // For DNS, the ClientConn target will be used for name resolution.
    93  //
    94  // For EDS, if EDSServiceName is not empty, it will be used for watching. If
    95  // EDSServiceName is empty, Cluster will be used.
    96  type DiscoveryMechanism struct {
    97  	// Cluster is the cluster name.
    98  	Cluster string `json:"cluster,omitempty"`
    99  	// LoadReportingServerName is the LRS server to send load reports to. If
   100  	// not present, load reporting will be disabled. If set to the empty string,
   101  	// load reporting will be sent to the same server that we obtained CDS data
   102  	// from.
   103  	LoadReportingServerName *string `json:"lrsLoadReportingServerName,omitempty"`
   104  	// MaxConcurrentRequests is the maximum number of outstanding requests can
   105  	// be made to the upstream cluster. Default is 1024.
   106  	MaxConcurrentRequests *uint32 `json:"maxConcurrentRequests,omitempty"`
   107  	// Type is the discovery mechanism type.
   108  	Type DiscoveryMechanismType `json:"type,omitempty"`
   109  	// EDSServiceName is the EDS service name, as returned in CDS. May be unset
   110  	// if not specified in CDS. For type EDS only.
   111  	//
   112  	// This is used for EDS watch if set. If unset, Cluster is used for EDS
   113  	// watch.
   114  	EDSServiceName string `json:"edsServiceName,omitempty"`
   115  	// DNSHostname is the DNS name to resolve in "host:port" form. For type
   116  	// LOGICAL_DNS only.
   117  	DNSHostname string `json:"dnsHostname,omitempty"`
   118  }
   119  
   120  // Equal returns whether the DiscoveryMechanism is the same with the parameter.
   121  func (dm DiscoveryMechanism) Equal(b DiscoveryMechanism) bool {
   122  	switch {
   123  	case dm.Cluster != b.Cluster:
   124  		return false
   125  	case !equalStringP(dm.LoadReportingServerName, b.LoadReportingServerName):
   126  		return false
   127  	case !equalUint32P(dm.MaxConcurrentRequests, b.MaxConcurrentRequests):
   128  		return false
   129  	case dm.Type != b.Type:
   130  		return false
   131  	case dm.EDSServiceName != b.EDSServiceName:
   132  		return false
   133  	case dm.DNSHostname != b.DNSHostname:
   134  		return false
   135  	}
   136  	return true
   137  }
   138  
   139  func equalStringP(a, b *string) bool {
   140  	if a == nil && b == nil {
   141  		return true
   142  	}
   143  	if a == nil || b == nil {
   144  		return false
   145  	}
   146  	return *a == *b
   147  }
   148  
   149  func equalUint32P(a, b *uint32) bool {
   150  	if a == nil && b == nil {
   151  		return true
   152  	}
   153  	if a == nil || b == nil {
   154  		return false
   155  	}
   156  	return *a == *b
   157  }
   158  
   159  // LBConfig is the config for cluster resolver balancer.
   160  type LBConfig struct {
   161  	serviceconfig.LoadBalancingConfig `json:"-"`
   162  	// DiscoveryMechanisms is an ordered list of discovery mechanisms.
   163  	//
   164  	// Must have at least one element. Results from each discovery mechanism are
   165  	// concatenated together in successive priorities.
   166  	DiscoveryMechanisms []DiscoveryMechanism `json:"discoveryMechanisms,omitempty"`
   167  
   168  	// XDSLBPolicy specifies the policy for locality picking and endpoint picking.
   169  	//
   170  	// Note that it's not normal balancing policy, and it can only be either
   171  	// ROUND_ROBIN or RING_HASH.
   172  	//
   173  	// For ROUND_ROBIN, the policy name will be "ROUND_ROBIN", and the config
   174  	// will be empty. This sets the locality-picking policy to weighted_target
   175  	// and the endpoint-picking policy to round_robin.
   176  	//
   177  	// For RING_HASH, the policy name will be "RING_HASH", and the config will
   178  	// be lb config for the ring_hash_experimental LB Policy. ring_hash policy
   179  	// is responsible for both locality picking and endpoint picking.
   180  	XDSLBPolicy *internalserviceconfig.BalancerConfig `json:"xdsLbPolicy,omitempty"`
   181  }
   182  
   183  const (
   184  	rrName = roundrobin.Name
   185  	rhName = ringhash.Name
   186  )
   187  
   188  func parseConfig(c json.RawMessage) (*LBConfig, error) {
   189  	var cfg LBConfig
   190  	if err := json.Unmarshal(c, &cfg); err != nil {
   191  		return nil, err
   192  	}
   193  	if lbp := cfg.XDSLBPolicy; lbp != nil && !strings.EqualFold(lbp.Name, rrName) && !strings.EqualFold(lbp.Name, rhName) {
   194  		return nil, fmt.Errorf("unsupported child policy with name %q, not one of {%q,%q}", lbp.Name, rrName, rhName)
   195  	}
   196  	return &cfg, nil
   197  }