github.com/polarismesh/polaris@v1.17.8/apiserver/grpcserver/discover/v1/client_access.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package v1
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"io"
    24  	"strings"
    25  
    26  	apimodel "github.com/polarismesh/specification/source/go/api/v1/model"
    27  	apiservice "github.com/polarismesh/specification/source/go/api/v1/service_manage"
    28  	"go.uber.org/zap"
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/grpc/metadata"
    31  	"google.golang.org/grpc/peer"
    32  
    33  	"github.com/polarismesh/polaris/apiserver/grpcserver"
    34  	api "github.com/polarismesh/polaris/common/api/v1"
    35  	commonlog "github.com/polarismesh/polaris/common/log"
    36  	"github.com/polarismesh/polaris/common/utils"
    37  )
    38  
    39  var (
    40  	accesslog = commonlog.GetScopeOrDefaultByName(commonlog.APIServerLoggerName)
    41  )
    42  
    43  // ReportClient 客户端上报
    44  func (g *DiscoverServer) ReportClient(ctx context.Context, in *apiservice.Client) (*apiservice.Response, error) {
    45  	return g.namingServer.ReportClient(grpcserver.ConvertContext(ctx), in), nil
    46  }
    47  
    48  // RegisterInstance 注册服务实例
    49  func (g *DiscoverServer) RegisterInstance(ctx context.Context, in *apiservice.Instance) (*apiservice.Response, error) {
    50  	// 需要记录操作来源,提高效率,只针对特殊接口添加operator
    51  	rCtx := grpcserver.ConvertContext(ctx)
    52  	rCtx = context.WithValue(rCtx, utils.StringContext("operator"), ParseGrpcOperator(ctx))
    53  
    54  	// 客户端请求中带了 token 的,优先已请求中的为准
    55  	if in.GetServiceToken().GetValue() != "" {
    56  		rCtx = context.WithValue(rCtx, utils.ContextAuthTokenKey, in.GetServiceToken().GetValue())
    57  	}
    58  
    59  	grpcHeader := rCtx.Value(utils.ContextGrpcHeader).(metadata.MD)
    60  
    61  	if _, ok := grpcHeader["async-regis"]; ok {
    62  		rCtx = context.WithValue(rCtx, utils.ContextOpenAsyncRegis, true)
    63  	}
    64  
    65  	out := g.namingServer.RegisterInstance(rCtx, in)
    66  	return out, nil
    67  }
    68  
    69  // DeregisterInstance 反注册服务实例
    70  func (g *DiscoverServer) DeregisterInstance(
    71  	ctx context.Context, in *apiservice.Instance) (*apiservice.Response, error) {
    72  	// 需要记录操作来源,提高效率,只针对特殊接口添加operator
    73  	rCtx := grpcserver.ConvertContext(ctx)
    74  	rCtx = context.WithValue(rCtx, utils.StringContext("operator"), ParseGrpcOperator(ctx))
    75  
    76  	// 客户端请求中带了 token 的,优先已请求中的为准
    77  	if in.GetServiceToken().GetValue() != "" {
    78  		rCtx = context.WithValue(rCtx, utils.ContextAuthTokenKey, in.GetServiceToken().GetValue())
    79  	}
    80  
    81  	out := g.namingServer.DeregisterInstance(rCtx, in)
    82  	return out, nil
    83  }
    84  
    85  // Discover 统一发现接口
    86  func (g *DiscoverServer) Discover(server apiservice.PolarisGRPC_DiscoverServer) error {
    87  	ctx := grpcserver.ConvertContext(server.Context())
    88  	clientIP, _ := ctx.Value(utils.StringContext("client-ip")).(string)
    89  	clientAddress, _ := ctx.Value(utils.StringContext("client-address")).(string)
    90  	requestID, _ := ctx.Value(utils.StringContext("request-id")).(string)
    91  	userAgent, _ := ctx.Value(utils.StringContext("user-agent")).(string)
    92  	method, _ := grpc.MethodFromServerStream(server)
    93  
    94  	for {
    95  		in, err := server.Recv()
    96  		if err != nil {
    97  			if io.EOF == err {
    98  				return nil
    99  			}
   100  			return err
   101  		}
   102  
   103  		msg := fmt.Sprintf("receive grpc discover request: %s", in.Service.String())
   104  		accesslog.Info(msg,
   105  			zap.String("type", apiservice.DiscoverRequest_DiscoverRequestType_name[int32(in.Type)]),
   106  			zap.String("client-address", clientAddress),
   107  			zap.String("user-agent", userAgent),
   108  			utils.ZapRequestID(requestID),
   109  		)
   110  
   111  		// 是否允许访问
   112  		if ok := g.allowAccess(method); !ok {
   113  			resp := api.NewDiscoverResponse(apimodel.Code_ClientAPINotOpen)
   114  			if sendErr := server.Send(resp); sendErr != nil {
   115  				return sendErr
   116  			}
   117  			continue
   118  		}
   119  
   120  		// stream模式,需要对每个包进行检测
   121  		if code := g.enterRateLimit(clientIP, method); code != uint32(apimodel.Code_ExecuteSuccess) {
   122  			resp := api.NewDiscoverResponse(apimodel.Code(code))
   123  			if err = server.Send(resp); err != nil {
   124  				return err
   125  			}
   126  			continue
   127  		}
   128  
   129  		var out *apiservice.DiscoverResponse
   130  		switch in.Type {
   131  		case apiservice.DiscoverRequest_INSTANCE:
   132  			out = g.namingServer.ServiceInstancesCache(ctx, in.Service)
   133  		case apiservice.DiscoverRequest_ROUTING:
   134  			out = g.namingServer.GetRoutingConfigWithCache(ctx, in.Service)
   135  		case apiservice.DiscoverRequest_RATE_LIMIT:
   136  			out = g.namingServer.GetRateLimitWithCache(ctx, in.Service)
   137  		case apiservice.DiscoverRequest_CIRCUIT_BREAKER:
   138  			out = g.namingServer.GetCircuitBreakerWithCache(ctx, in.Service)
   139  		case apiservice.DiscoverRequest_SERVICES:
   140  			out = g.namingServer.GetServiceWithCache(ctx, in.Service)
   141  		case apiservice.DiscoverRequest_FAULT_DETECTOR:
   142  			out = g.namingServer.GetFaultDetectWithCache(ctx, in.Service)
   143  		default:
   144  			out = api.NewDiscoverRoutingResponse(apimodel.Code_InvalidDiscoverResource, in.Service)
   145  		}
   146  
   147  		err = server.Send(out)
   148  		if err != nil {
   149  			return err
   150  		}
   151  	}
   152  }
   153  
   154  // Heartbeat 上报心跳
   155  func (g *DiscoverServer) Heartbeat(ctx context.Context, in *apiservice.Instance) (*apiservice.Response, error) {
   156  	return g.healthCheckServer.Report(grpcserver.ConvertContext(ctx), in), nil
   157  }
   158  
   159  // BatchHeartbeat 批量上报心跳
   160  func (g *DiscoverServer) BatchHeartbeat(svr apiservice.PolarisHeartbeatGRPC_BatchHeartbeatServer) error {
   161  	ctx := grpcserver.ConvertContext(svr.Context())
   162  
   163  	for {
   164  		req, err := svr.Recv()
   165  		if err != nil {
   166  			if io.EOF == err {
   167  				return nil
   168  			}
   169  			return err
   170  		}
   171  
   172  		_ = g.healthCheckServer.Reports(ctx, req.GetHeartbeats())
   173  		if err = svr.Send(&apiservice.HeartbeatsResponse{}); err != nil {
   174  			return err
   175  		}
   176  	}
   177  }
   178  
   179  // ParseGrpcOperator 构造请求源
   180  func ParseGrpcOperator(ctx context.Context) string {
   181  	// 获取请求源
   182  	operator := "GRPC"
   183  	if pr, ok := peer.FromContext(ctx); ok && pr.Addr != nil {
   184  		addrSlice := strings.Split(pr.Addr.String(), ":")
   185  		if len(addrSlice) == 2 {
   186  			operator += ":" + addrSlice[0]
   187  		}
   188  	}
   189  	return operator
   190  }