diff --git a/go.mod b/go.mod index ac69a20ecd88..fa80daf1df6e 100644 --- a/go.mod +++ b/go.mod @@ -27,6 +27,7 @@ require ( github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 go.uber.org/mock v0.4.0 golang.org/x/net v0.24.0 + golang.org/x/sync v0.7.0 golang.org/x/term v0.19.0 golang.org/x/text v0.14.0 golang.org/x/time v0.5.0 @@ -174,7 +175,6 @@ require ( golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect diff --git a/pkg/util/proxy/proxy.go b/pkg/util/proxy/proxy.go index 3e75108fb84b..36446e1a70a4 100644 --- a/pkg/util/proxy/proxy.go +++ b/pkg/util/proxy/proxy.go @@ -26,8 +26,10 @@ import ( "net/url" "path" "strings" + "sync" "time" + "golang.org/x/sync/singleflight" authenticationv1 "k8s.io/api/authentication/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/httpstream" @@ -44,6 +46,13 @@ import ( // SecretGetterFunc is a function to get secret. type SecretGetterFunc func(context.Context, string, string) (*corev1.Secret, error) +type clusterEndpointInfo struct { + Transport *http.Transport +} + +var clusterEndpointInfoStore sync.Map +var singleExecution singleflight.Group + // ConnectCluster returns a handler for proxy cluster. func ConnectCluster(ctx context.Context, cluster *clusterapis.Cluster, proxyPath string, secretGetter SecretGetterFunc, responder registryrest.Responder) (http.Handler, error) { tlsConfig, err := GetTLSConfigForCluster(ctx, cluster, secretGetter) @@ -159,12 +168,32 @@ func Location(cluster *clusterapis.Cluster, tlsConfig *tls.Config) (*url.URL, ht return nil, nil, err } - proxyTransport, err := createProxyTransport(cluster, tlsConfig) + if v, ok := clusterEndpointInfoStore.Load(cluster.UID); ok { + clusterEndpointsInfo := v.(clusterEndpointInfo) + return location, clusterEndpointsInfo.Transport, nil + } + + endpointInfo, err, _ := singleExecution.Do(string(cluster.UID), func() (interface{}, error) { + if value, ok := clusterEndpointInfoStore.Load(cluster.UID); ok { + return value, nil + } + proxyTransport, err := createProxyTransport(cluster, tlsConfig) + if err != nil { + return nil, err + } + clusterEndpointInfoo := clusterEndpointInfo{ + Transport: proxyTransport, + } + clusterEndpointInfoStore.Store(cluster.UID, clusterEndpointInfo{ + Transport: proxyTransport, + }) + return clusterEndpointInfoo, nil + }) if err != nil { return nil, nil, err } - - return location, proxyTransport, nil + transport := endpointInfo.(clusterEndpointInfo).Transport + return location, transport, nil } func constructLocation(cluster *clusterapis.Cluster) (*url.URL, error) {