Skip to content

Commit

Permalink
fix:值支持不等于标签逻辑 (#185)
Browse files Browse the repository at this point in the history
  • Loading branch information
qdsordinarydream authored Nov 19, 2023
1 parent da06acf commit dd56f3c
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 4 deletions.
39 changes: 39 additions & 0 deletions pkg/model/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,12 +733,15 @@ type ServiceClusters interface {
GetExtendedCacheValue(pluginIndex int) interface{}
// SetExtendedCacheValue 设置扩展的缓存值,需要预初始化好,否则会有并发修改的问题
SetExtendedCacheValue(pluginIndex int, value interface{})
// GetInstancesWithMetaValuesNotEqual 获取该标签不等于指定标签值的实例集合
GetInstancesWithMetaValuesNotEqual(location Location, metaKey string, metavalue string) map[string]string
}

// LocationBasedMetaKey 基于某个地域信息的元数据查询key
type LocationBasedMetaKey struct {
location Location
metaKey string
keyType int // 0: equal, 1: not equal
}

// metaDataInService 标签缓存信息
Expand Down Expand Up @@ -1014,6 +1017,42 @@ func (c *clusterCache) SetExtendedCacheValue(pluginIndex int, value interface{})
c.extendedCacheValues.Store(pluginIndex, value)
}

// GetInstancesWithMetaValuesNotEqual 获取该标签不等于指定标签值的实例集合
func (c *clusterCache) GetInstancesWithMetaValuesNotEqual(location Location, metaKey string, metaValue string) map[string]string {
var value interface{}
var exists bool
locationKey := LocationBasedMetaKey{location: location, metaKey: metaKey, keyType: 1}
value, exists = c.svcLevelMetadata.metaDataSet.Load(locationKey)
if exists {
return value.(map[string]string)
}
// 按需构建指定地域的实例元数据集合
instances := c.svcInstances.GetInstances()
metaValueSet := make(map[string]string, 0)
for _, instance := range instances {
if !matchLocation(instance, location) {
continue
}
if instance.IsIsolated() || instance.GetWeight() == 0 || !instance.IsHealthy() {
continue
}
metadata := instance.GetMetadata()
if len(metadata) == 0 {
continue
}
val, ok := metadata[metaKey]
if !ok {
continue
}
if val == metaValue {
continue
}
metaValueSet[val] = buildComposedValue(metaKey, val)
}
value, _ = c.svcLevelMetadata.metaDataSet.LoadOrStore(locationKey, metaValueSet)
return value.(map[string]string)
}

// matchMetadata 标签匹配
func (c *Cluster) matchMetadata(instance Instance) bool {
if c.MetaCount == 0 {
Expand Down
24 changes: 20 additions & 4 deletions plugin/servicerouter/rulebase/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,14 +359,19 @@ func (g *RuleBasedInstancesFilter) matchDstMetadata(routeInfo *servicerouter.Rou
// 首先如果元数据的value无法获取,直接匹配失败
return nil, false, "", nil
}

// 全匹配类型直接返回全量实例
if ruleMetaValueStr == matchAll && ruleMetaValue.ValueType == apimodel.MatchString_TEXT {
return cls, true, "", nil
}
metaValues := svcCache.GetInstanceMetaValues(cls.Location, ruleMetaKey)
if len(metaValues) == 0 {
// 不匹配
return nil, false, "", nil
// 如果是“不等于”类型,需要单独处理
var metaValues map[string]string
if ruleMetaValue.Type != apimodel.MatchString_NOT_EQUALS {
metaValues = svcCache.GetInstanceMetaValues(cls.Location, ruleMetaKey)
if len(metaValues) == 0 {
// 不匹配
return nil, false, "", nil
}
}
switch ruleMetaValue.Type {
case apimodel.MatchString_REGEX:
Expand Down Expand Up @@ -399,6 +404,17 @@ func (g *RuleBasedInstancesFilter) matchDstMetadata(routeInfo *servicerouter.Rou
if !hasMatchedValue {
return nil, false, "", nil
}

case apimodel.MatchString_NOT_EQUALS:
metaValues = svcCache.GetInstancesWithMetaValuesNotEqual(cls.Location, ruleMetaKey, ruleMetaValueStr)
if len(metaValues) == 0 {
return cls, false, "", nil
}
for k, v := range metaValues {
cls.RuleAddMetadata(ruleMetaKey, k, v)
}
metaChanged = true

// parameter、variable、text 的 exact 最终都是要精确匹配,只是匹配的值来源不同
default:
// 校验从上一个路由插件继承下来的规则是否符合该目标规则
Expand Down

0 comments on commit dd56f3c

Please sign in to comment.