package connect import ( "context" "fmt" "github.com/hashicorp/consul/api" "speech-nlu-parse/global" "sync" "time" "google.golang.org/grpc" "google.golang.org/grpc/balancer/roundrobin" "google.golang.org/grpc/credentials/insecure" ) // 技能服务连接句柄 var skillConn sync.Map // 获取GRPC服务连接句柄 func GrpcConn(serverName string) (*grpc.ClientConn, error) { if conn, ok := skillConn.Load(serverName); ok { return conn.(*grpc.ClientConn), nil } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() // 通过 Consul 客户端查询服务实例 consulConfig := api.DefaultConfig() consulConfig.Address = global.ServerSetting.ConsulAddr client, err := api.NewClient(consulConfig) if err != nil { return nil, fmt.Errorf("consul client init failed: %v", err) } entries, _, err := client.Health().Service(serverName, "", true, nil) if err != nil { global.Logger.Errorf("consul get service %s failed: %v", serverName, err) return nil, fmt.Errorf("consul get service %s failed: %v", serverName, err) } // 健康实例检查 if len(entries) == 0 { return nil, fmt.Errorf("no available instances for service [%s]", serverName) } // 获取第一个健康实例的地址 targetAddr := fmt.Sprintf("%s:%d", entries[0].Service.Address, entries[0].Service.Port) fmt.Println(targetAddr) opts := []grpc.DialOption{ //grpc.WithBlock(), //阻塞连接直到成功或超时,存在缺陷 grpc.WithTransportCredentials(insecure.NewCredentials()), //指定传输层安全性的凭据 grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"LoadBalancingPolicy": "%s"}`, roundrobin.Name)), // 设置默认的负载均衡策略 } conn, err := grpc.DialContext(ctx, targetAddr, opts...) if err != nil { return nil, err } skillConn.Store(serverName, conn) return conn, nil }