github.com/polarismesh/polaris@v1.17.8/apiserver/l5pbserver/server.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 l5pbserver
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"net"
    24  	"time"
    25  
    26  	"go.uber.org/zap"
    27  
    28  	"github.com/polarismesh/polaris/apiserver"
    29  	"github.com/polarismesh/polaris/common/api/l5"
    30  	"github.com/polarismesh/polaris/common/metrics"
    31  	"github.com/polarismesh/polaris/plugin"
    32  	"github.com/polarismesh/polaris/service"
    33  )
    34  
    35  const (
    36  	success            int32  = 100
    37  	sohSize            int    = 2
    38  	headSize           int    = 6
    39  	maxSize            int    = 1024 * 1024 * 2
    40  	defaultClusterName string = "cl5.discover"
    41  )
    42  
    43  // cl5Request 每个链接,封装为一个请求
    44  type cl5Request struct {
    45  	conn       net.Conn
    46  	start      time.Time
    47  	clientAddr string
    48  	cmd        int32
    49  	code       l5Code
    50  }
    51  
    52  // L5pbserver CL5 API服务器
    53  type L5pbserver struct {
    54  	listenIP    string
    55  	listenPort  uint32
    56  	clusterName string // 集群名
    57  
    58  	listener     net.Listener
    59  	namingServer service.DiscoverServer
    60  	statis       plugin.Statis
    61  }
    62  
    63  // GetPort 获取端口
    64  func (l *L5pbserver) GetPort() uint32 {
    65  	return l.listenPort
    66  }
    67  
    68  // GetProtocol 获取Server的协议
    69  func (l *L5pbserver) GetProtocol() string {
    70  	return "l5pb"
    71  }
    72  
    73  // Initialize 初始化CL5 API服务器
    74  func (l *L5pbserver) Initialize(_ context.Context, option map[string]interface{},
    75  	_ map[string]apiserver.APIConfig) error {
    76  	l.listenIP = option["listenIP"].(string)
    77  	l.listenPort = uint32(option["listenPort"].(int))
    78  	// 获取当前集群
    79  	l.clusterName = defaultClusterName
    80  	if clusterName, _ := option["clusterName"].(string); clusterName != "" {
    81  		l.clusterName = clusterName
    82  	}
    83  
    84  	return nil
    85  }
    86  
    87  // Run 启动CL5 API服务器
    88  func (l *L5pbserver) Run(errCh chan error) {
    89  	log.Infof("start l5pbserver")
    90  
    91  	var err error
    92  	// 引入功能模块和插件
    93  	l.namingServer, err = service.GetServer()
    94  	if err != nil {
    95  		log.Errorf("%v", err)
    96  		errCh <- err
    97  		return
    98  	}
    99  	l.statis = plugin.GetStatis()
   100  
   101  	// 初始化 l5pb server
   102  	address := fmt.Sprintf("%v:%v", l.listenIP, l.listenPort)
   103  	listener, err := net.Listen("tcp", address)
   104  	if err != nil {
   105  		log.Errorf("listen error: %v", err)
   106  		errCh <- err
   107  		return
   108  	}
   109  	l.listener = listener
   110  
   111  	for {
   112  		conn, err := listener.Accept()
   113  		if err != nil {
   114  			log.Errorf("accept error: %v", err)
   115  			errCh <- err
   116  			return
   117  		}
   118  		// log.Infof("new connect: %v", conn.RemoteAddr())
   119  		go l.handleConnection(conn)
   120  	}
   121  }
   122  
   123  // Stop server
   124  func (l *L5pbserver) Stop() {
   125  	if l.listener != nil {
   126  		_ = l.listener.Close()
   127  	}
   128  }
   129  
   130  // Restart restart server
   131  func (l *L5pbserver) Restart(_ map[string]interface{}, _ map[string]apiserver.APIConfig,
   132  	_ chan error) error {
   133  	return nil
   134  }
   135  
   136  // PreProcess 请求预处理:限频/鉴权
   137  func (l *L5pbserver) PreProcess(req *cl5Request) bool {
   138  	log.Info("[Cl5] handle request", zap.String("ClientAddr", req.clientAddr), zap.Int32("Cmd", req.cmd))
   139  	var result = true
   140  	// 访问频率限制
   141  
   142  	// 访问权限控制
   143  
   144  	return result
   145  }
   146  
   147  // PostProcess 请求后处理:统计/告警
   148  func (l *L5pbserver) PostProcess(req *cl5Request) {
   149  	now := time.Now()
   150  	// 统计
   151  	cmdStr, ok := l5.CL5_CMD_name[req.cmd]
   152  	if !ok {
   153  		cmdStr = "Unrecognizable_Cmd"
   154  	}
   155  
   156  	diff := now.Sub(req.start)
   157  	// 打印耗时超过1s的请求
   158  	if diff > time.Second {
   159  		log.Info("handling time > 1s",
   160  			zap.String("client-addr", req.clientAddr),
   161  			zap.String("cmd", cmdStr),
   162  			zap.Duration("handling-time", diff),
   163  		)
   164  	}
   165  	code := calL5Code(req.code)
   166  	l.statis.ReportCallMetrics(metrics.CallMetric{
   167  		Type:     metrics.ServerCallMetric,
   168  		API:      cmdStr,
   169  		Protocol: "HTTP",
   170  		Code:     int(code),
   171  		Duration: diff,
   172  	})
   173  	// 告警
   174  }
   175  
   176  func calL5Code(code l5Code) int {
   177  	switch code {
   178  	case l5Success:
   179  		return 200
   180  	case l5ResponseFailed:
   181  		return -1
   182  	case l5UnmarshalPacketFailed:
   183  		return 400
   184  	default:
   185  		return 500
   186  	}
   187  }