package logic import ( "context" "fmt" "github.com/gin-gonic/gin" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/resolver" "google.golang.org/protobuf/types/known/emptypb" "net/http" "sonet/api/gen/postal" "sonet/internal/gateway_http/config" "sonet/pkg/grpc/balancer" "sonet/pkg/grpc/discovery" "sonet/pkg/utils/resp" ) type PostalBalancer struct { postalClient postal.PostalClient } func NewPostalBalancer() *PostalBalancer { return &PostalBalancer{} } func (h *PostalBalancer) Init(ctx context.Context, resolver resolver.Builder) { balancer.InitConsistentHashBuilder() postalUrl := discovery.EtcdDialUrl(postal.Postal_ServiceDesc.ServiceName) conn, err := grpc.DialContext(ctx, postalUrl, grpc.WithTransportCredentials(insecure.NewCredentials()), // consistent hash lb grpc.WithDefaultServiceConfig(fmt.Sprintf(`{"loadBalancingPolicy":"%s"}`, balancer.ConsistentHash)), grpc.WithResolvers(resolver), ) if err != nil { return } h.postalClient = postal.NewPostalClient(conn) } // Endpoint 根据consistent hash负载均衡策略调用到 postal 集群的一个节点,拿到节点的客户端连接地址 func (h *PostalBalancer) Endpoint(c *gin.Context) { subject, err := config.GetSubject(c) if err != nil { c.JSON(http.StatusBadRequest, resp.Fail(err.Error())) return } ctx := context.WithValue(context.Background(), balancer.ConsistentHashKey, subject.Uid) res, err := h.postalClient.Endpoint(ctx, &emptypb.Empty{}) if err != nil { c.JSON(http.StatusInternalServerError, resp.Error(err.Error())) return } c.JSON(http.StatusOK, resp.Success(resp.H{"ws": res.Endpoint})) }