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 }