mirror of
https://github.com/alibaba/higress.git
synced 2026-06-07 03:37:28 +08:00
feat: Support adding a proxy server in between when forwarding requests to upstream (#2710)
Co-authored-by: 澄潭 <zty98751@alibaba-inc.com>
This commit is contained in:
@@ -21,8 +21,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
higressconfig "github.com/alibaba/higress/pkg/config"
|
||||
"github.com/alibaba/higress/registry"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
@@ -33,44 +31,56 @@ import (
|
||||
"istio.io/pkg/log"
|
||||
|
||||
"github.com/alibaba/higress/pkg/common"
|
||||
higressconfig "github.com/alibaba/higress/pkg/config"
|
||||
ingress "github.com/alibaba/higress/pkg/ingress/kube/common"
|
||||
"github.com/alibaba/higress/registry"
|
||||
)
|
||||
|
||||
type Cache interface {
|
||||
UpdateServiceWrapper(service string, data *ServiceWrapper)
|
||||
UpdateServiceWrapper(service string, data *ingress.ServiceWrapper)
|
||||
DeleteServiceWrapper(service string)
|
||||
UpdateProxyWrapper(name string, data *ingress.ProxyWrapper)
|
||||
DeleteProxyWrapper(name string)
|
||||
UpdateConfigCache(kind config.GroupVersionKind, key string, config *config.Config, forceDelete bool)
|
||||
GetAllConfigs(kind config.GroupVersionKind) map[string]*config.Config
|
||||
PurgeStaleService()
|
||||
PurgeStaleItems() bool
|
||||
UpdateServiceEntryEndpointWrapper(service, ip, regionId, zoneId, protocol string, labels map[string]string)
|
||||
GetServiceByEndpoints(requestVersions, endpoints map[string]bool, versionKey string, protocol common.Protocol) map[string][]string
|
||||
GetAllServiceEntry() []*v1alpha3.ServiceEntry
|
||||
GetAllServiceWrapper() []*ServiceWrapper
|
||||
GetAllServiceWrapper() []*ingress.ServiceWrapper
|
||||
GetAllProxyWrapper() []*ingress.ProxyWrapper
|
||||
GetAllDestinationRuleWrapper() []*ingress.WrapperDestinationRule
|
||||
GetIncrementalServiceWrapper() (updatedList []*ServiceWrapper, deletedList []*ServiceWrapper)
|
||||
GetIncrementalServiceWrapper() (updatedList []*ingress.ServiceWrapper, deletedList []*ingress.ServiceWrapper)
|
||||
RemoveEndpointByIp(ip string)
|
||||
}
|
||||
|
||||
func NewCache() Cache {
|
||||
return &store{
|
||||
mux: &sync.RWMutex{},
|
||||
sew: make(map[string]*ServiceWrapper),
|
||||
configs: make(map[string]map[string]*config.Config),
|
||||
toBeUpdated: make([]*ServiceWrapper, 0),
|
||||
toBeDeleted: make([]*ServiceWrapper, 0),
|
||||
ip2services: make(map[string]map[string]bool),
|
||||
deferedDelete: make(map[string]struct{}),
|
||||
mux: &sync.RWMutex{},
|
||||
configs: make(map[string]map[string]*config.Config),
|
||||
sew: make(map[string]*ingress.ServiceWrapper),
|
||||
toBeUpdated: make([]*ingress.ServiceWrapper, 0),
|
||||
toBeDeleted: make([]*ingress.ServiceWrapper, 0),
|
||||
ip2services: make(map[string]map[string]bool),
|
||||
deferredDeleteServices: make(map[string]struct{}),
|
||||
pw: make(map[string]*ingress.ProxyWrapper),
|
||||
deferredDeleteProxies: make(map[string]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
type store struct {
|
||||
mux *sync.RWMutex
|
||||
sew map[string]*ServiceWrapper
|
||||
configs map[string]map[string]*config.Config
|
||||
toBeUpdated []*ServiceWrapper
|
||||
toBeDeleted []*ServiceWrapper
|
||||
ip2services map[string]map[string]bool
|
||||
deferedDelete map[string]struct{}
|
||||
mux *sync.RWMutex
|
||||
|
||||
configs map[string]map[string]*config.Config
|
||||
|
||||
sew map[string]*ingress.ServiceWrapper
|
||||
toBeUpdated []*ingress.ServiceWrapper
|
||||
toBeDeleted []*ingress.ServiceWrapper
|
||||
ip2services map[string]map[string]bool
|
||||
deferredDeleteServices map[string]struct{}
|
||||
|
||||
pw map[string]*ingress.ProxyWrapper
|
||||
deferredDeleteProxies map[string]struct{}
|
||||
}
|
||||
|
||||
func (s *store) GetAllConfigs(kind config.GroupVersionKind) map[string]*config.Config {
|
||||
@@ -179,14 +189,12 @@ func (s *store) UpdateServiceEntryEndpointWrapper(service, ip, regionId, zoneId,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *store) UpdateServiceWrapper(service string, data *ServiceWrapper) {
|
||||
func (s *store) UpdateServiceWrapper(service string, data *ingress.ServiceWrapper) {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
|
||||
@@ -196,16 +204,16 @@ func (s *store) UpdateServiceWrapper(service string, data *ServiceWrapper) {
|
||||
data.SetCreateTime(time.Now())
|
||||
}
|
||||
|
||||
log.Debugf("mcp service entry update, name:%s, data:%v", service, data)
|
||||
log.Debugf("mcp service entry update, name: %s, data: %v", service, data)
|
||||
|
||||
s.toBeUpdated = append(s.toBeUpdated, data)
|
||||
s.sew[service] = data
|
||||
// service is updated, should not be deleted
|
||||
if _, ok := s.deferedDelete[service]; ok {
|
||||
delete(s.deferedDelete, service)
|
||||
log.Debugf("service in deferedDelete updated, host:%s", service)
|
||||
if _, ok := s.deferredDeleteServices[service]; ok {
|
||||
delete(s.deferredDeleteServices, service)
|
||||
log.Debugf("service in deferredDeleteServices updated, host: %s", service)
|
||||
}
|
||||
log.Infof("ServiceEntry updated, host:%s", service)
|
||||
log.Infof("ServiceEntry updated, host: %s", service)
|
||||
}
|
||||
|
||||
func (s *store) DeleteServiceWrapper(service string) {
|
||||
@@ -214,19 +222,64 @@ func (s *store) DeleteServiceWrapper(service string) {
|
||||
|
||||
if data, exist := s.sew[service]; exist {
|
||||
s.toBeDeleted = append(s.toBeDeleted, data)
|
||||
s.deferedDelete[service] = struct{}{}
|
||||
s.deferredDeleteServices[service] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) UpdateProxyWrapper(name string, data *ingress.ProxyWrapper) {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
|
||||
if old, exist := s.pw[name]; exist {
|
||||
data.SetCreateTime(old.GetCreateTime())
|
||||
} else {
|
||||
data.SetCreateTime(time.Now())
|
||||
}
|
||||
|
||||
log.Debugf("mcp proxy entry update, name: %s, data: %v", name, data)
|
||||
|
||||
s.pw[name] = data
|
||||
// service is updated, should not be deleted
|
||||
if _, ok := s.deferredDeleteServices[name]; ok {
|
||||
delete(s.deferredDeleteServices, name)
|
||||
log.Debugf("proxy in deferredDeleteProxies updated, na: %s", name)
|
||||
}
|
||||
log.Infof("ProxyWrapper updated, name: %s", name)
|
||||
}
|
||||
|
||||
func (s *store) DeleteProxyWrapper(name string) {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
|
||||
if _, exist := s.pw[name]; exist {
|
||||
s.deferredDeleteProxies[name] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// should only be called when reconcile is done
|
||||
func (s *store) PurgeStaleService() {
|
||||
func (s *store) PurgeStaleItems() bool {
|
||||
s.mux.Lock()
|
||||
defer s.mux.Unlock()
|
||||
for service := range s.deferedDelete {
|
||||
|
||||
deleted := false
|
||||
|
||||
for service := range s.deferredDeleteServices {
|
||||
delete(s.sew, service)
|
||||
delete(s.deferedDelete, service)
|
||||
log.Infof("ServiceEntry deleted, host:%s", service)
|
||||
delete(s.deferredDeleteServices, service)
|
||||
log.Infof("ServiceEntry deleted, host: %s", service)
|
||||
|
||||
deleted = true
|
||||
}
|
||||
|
||||
for proxy := range s.deferredDeleteProxies {
|
||||
delete(s.pw, proxy)
|
||||
delete(s.deferredDeleteProxies, proxy)
|
||||
log.Infof("ProxyWrapper deleted, name: %s", proxy)
|
||||
|
||||
deleted = true
|
||||
}
|
||||
|
||||
return deleted
|
||||
}
|
||||
|
||||
// GetServiceByEndpoints get the list of services of which "address:port" contained by the endpoints
|
||||
@@ -292,18 +345,30 @@ func (s *store) GetAllServiceEntry() []*v1alpha3.ServiceEntry {
|
||||
}
|
||||
|
||||
// GetAllServiceWrapper get all ServiceWrapper in the store for xds push
|
||||
func (s *store) GetAllServiceWrapper() []*ServiceWrapper {
|
||||
func (s *store) GetAllServiceWrapper() []*ingress.ServiceWrapper {
|
||||
s.mux.RLock()
|
||||
defer s.mux.RUnlock()
|
||||
defer s.cleanUpdateAndDeleteArray()
|
||||
|
||||
sewList := make([]*ServiceWrapper, 0)
|
||||
sewList := make([]*ingress.ServiceWrapper, 0)
|
||||
for _, serviceEntryWrapper := range s.sew {
|
||||
sewList = append(sewList, serviceEntryWrapper.DeepCopy())
|
||||
}
|
||||
return sewList
|
||||
}
|
||||
|
||||
// GetAllProxyWrapper get all ServiceWrapper in the store for xds push
|
||||
func (s *store) GetAllProxyWrapper() []*ingress.ProxyWrapper {
|
||||
s.mux.RLock()
|
||||
defer s.mux.RUnlock()
|
||||
|
||||
pwList := make([]*ingress.ProxyWrapper, 0)
|
||||
for _, pw := range s.pw {
|
||||
pwList = append(pwList, pw.DeepCopy())
|
||||
}
|
||||
return pwList
|
||||
}
|
||||
|
||||
// GetAllDestinationRuleWrapper get all DestinationRuleWrapper in the store for xds push
|
||||
func (s *store) GetAllDestinationRuleWrapper() []*ingress.WrapperDestinationRule {
|
||||
s.mux.RLock()
|
||||
@@ -329,17 +394,17 @@ func (s *store) GetAllDestinationRuleWrapper() []*ingress.WrapperDestinationRule
|
||||
}
|
||||
|
||||
// GetIncrementalServiceWrapper get incremental ServiceWrapper in the store for xds push
|
||||
func (s *store) GetIncrementalServiceWrapper() ([]*ServiceWrapper, []*ServiceWrapper) {
|
||||
func (s *store) GetIncrementalServiceWrapper() ([]*ingress.ServiceWrapper, []*ingress.ServiceWrapper) {
|
||||
s.mux.RLock()
|
||||
defer s.mux.RUnlock()
|
||||
defer s.cleanUpdateAndDeleteArray()
|
||||
|
||||
updatedList := make([]*ServiceWrapper, 0)
|
||||
updatedList := make([]*ingress.ServiceWrapper, 0)
|
||||
for _, serviceEntryWrapper := range s.toBeUpdated {
|
||||
updatedList = append(updatedList, serviceEntryWrapper.DeepCopy())
|
||||
}
|
||||
|
||||
deletedList := make([]*ServiceWrapper, 0)
|
||||
deletedList := make([]*ingress.ServiceWrapper, 0)
|
||||
for _, serviceEntryWrapper := range s.toBeDeleted {
|
||||
deletedList = append(deletedList, serviceEntryWrapper.DeepCopy())
|
||||
}
|
||||
@@ -352,7 +417,7 @@ func (s *store) cleanUpdateAndDeleteArray() {
|
||||
s.toBeDeleted = nil
|
||||
}
|
||||
|
||||
func (s *store) updateIpMap(service string, data *ServiceWrapper) {
|
||||
func (s *store) updateIpMap(service string, data *ingress.ServiceWrapper) {
|
||||
for _, ep := range data.ServiceEntry.Endpoints {
|
||||
if s.ip2services[ep.Address] == nil {
|
||||
s.ip2services[ep.Address] = make(map[string]bool)
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright (c) 2022 Alibaba Group Holding Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package memory
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"istio.io/api/networking/v1alpha3"
|
||||
|
||||
"github.com/alibaba/higress/pkg/ingress/kube/common"
|
||||
)
|
||||
|
||||
type ServiceWrapper struct {
|
||||
ServiceName string
|
||||
ServiceEntry *v1alpha3.ServiceEntry
|
||||
DestinationRuleWrapper *common.WrapperDestinationRule
|
||||
Suffix string
|
||||
RegistryType string
|
||||
RegistryName string
|
||||
createTime time.Time
|
||||
}
|
||||
|
||||
func (sew *ServiceWrapper) DeepCopy() *ServiceWrapper {
|
||||
res := &ServiceWrapper{}
|
||||
res = sew
|
||||
res.ServiceEntry = sew.ServiceEntry.DeepCopy()
|
||||
res.createTime = sew.GetCreateTime()
|
||||
|
||||
if sew.DestinationRuleWrapper != nil {
|
||||
res.DestinationRuleWrapper = sew.DestinationRuleWrapper
|
||||
res.DestinationRuleWrapper.DestinationRule = sew.DestinationRuleWrapper.DestinationRule.DeepCopy()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (sew *ServiceWrapper) SetCreateTime(createTime time.Time) {
|
||||
sew.createTime = createTime
|
||||
}
|
||||
|
||||
func (sew *ServiceWrapper) GetCreateTime() time.Time {
|
||||
return sew.createTime
|
||||
}
|
||||
Reference in New Issue
Block a user