Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix:值支持不等于标签逻辑 #185

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading