AlexStocks commented on code in PR #1017:
URL: https://github.com/apache/dubbo-go-pixiu/pull/1017#discussion_r3802788174


##########
pkg/filter/http/grpcproxy/connection_manager.go:
##########
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 grpcproxy
+
+import (
+       "context"
+       "fmt"
+       "sync"
+       "time"
+)
+
+import (
+       "golang.org/x/sync/singleflight"
+
+       "google.golang.org/grpc"
+       "google.golang.org/grpc/connectivity"
+       "google.golang.org/grpc/credentials/insecure"
+)
+
+const defaultGRPCDialTimeout = 5 * time.Second
+
+type grpcConnectionDialer func(context.Context, string) (*grpc.ClientConn, 
error)
+
+// grpcConnectionManager owns long-lived backend connections for the HTTP gRPC
+// proxy. A grpc.ClientConn is safe for concurrent use and multiplexes calls
+// over HTTP/2, so a sync.Pool is both unnecessary and incorrect here.
+type grpcConnectionManager struct {
+       connections sync.Map
+       creates     singleflight.Group
+       dial        grpcConnectionDialer
+       dialTimeout time.Duration
+       onRemove    func(*grpc.ClientConn)
+
+       mu     sync.Mutex
+       closed bool
+}
+
+func newGRPCConnectionManager() *grpcConnectionManager {
+       return &grpcConnectionManager{
+               dial:        dialGRPCConnection,
+               dialTimeout: defaultGRPCDialTimeout,
+       }
+}
+
+func dialGRPCConnection(ctx context.Context, endpoint string) 
(*grpc.ClientConn, error) {
+       return grpc.DialContext( //nolint:staticcheck // SA1019: the context is 
required to enforce the dial timeout.
+               ctx,
+               endpoint,
+               grpc.WithTransportCredentials(insecure.NewCredentials()),
+       )
+}
+
+func (m *grpcConnectionManager) Get(ctx context.Context, key, endpoint string) 
(*grpc.ClientConn, error) {
+       if key == "" || endpoint == "" {
+               return nil, fmt.Errorf("grpc connection key and endpoint must 
not be empty")
+       }
+       if ctx == nil {
+               ctx = context.Background()
+       }
+
+       if conn, ok := m.loadHealthy(key); ok {
+               return conn, nil
+       }
+
+       result := m.creates.DoChan(key, func() (any, error) {
+               if conn, ok := m.loadHealthy(key); ok {
+                       return conn, nil
+               }
+
+               m.mu.Lock()
+               if m.closed {
+                       m.mu.Unlock()
+                       return nil, fmt.Errorf("grpc connection manager is 
closed")
+               }
+               dial := m.dial
+               dialTimeout := m.dialTimeout
+               m.mu.Unlock()
+
+               dialCtx, cancel := context.WithTimeout(context.Background(), 
dialTimeout)
+               defer cancel()
+               conn, err := dial(dialCtx, endpoint)
+               if err != nil {
+                       return nil, err
+               }
+
+               m.mu.Lock()
+               closed := m.closed
+               if !closed {
+                       m.connections.Store(key, conn)

Review Comment:
   [P1] 当前 1024 项 LRU 仍会破坏 endpoint 删除语义。淘汰 candidate 时同时删除 
endpointGenerations、endpointEventVers 和 
endpointRemoved,管理器随后会把该地址当成从未删除。判别探针先删除 A,再删除 1025 个唯一地址使 A 的 tombstone 
淘汰,最后模拟一个删除前已选中 A、但尚未进入 Get 的延迟请求;当前 Head 会实际调用 dialer(返回 probe dial),而不是拒绝为 
grpc endpoint was removed。旧版本的 present 事件也会因 event version 
一并丢失而重新被接受。请让有界回收保留足以拒绝旧请求/旧事件的代次信息,或在拨号前对当前 cluster snapshot 
做等价校验,不能通过忘记删除状态来实现有界。



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to