github.com/polarismesh/polaris@v1.17.8/admin/maintain.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 admin 19 20 import ( 21 "context" 22 "errors" 23 "runtime/debug" 24 "time" 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 30 api "github.com/polarismesh/polaris/common/api/v1" 31 connlimit "github.com/polarismesh/polaris/common/conn/limit" 32 commonlog "github.com/polarismesh/polaris/common/log" 33 "github.com/polarismesh/polaris/common/model" 34 commonstore "github.com/polarismesh/polaris/common/store" 35 "github.com/polarismesh/polaris/common/utils" 36 "github.com/polarismesh/polaris/plugin" 37 ) 38 39 func (s *Server) GetServerConnections(_ context.Context, req *ConnReq) (*ConnCountResp, error) { 40 if req.Protocol == "" { 41 return nil, errors.New("missing param protocol") 42 } 43 44 lis := connlimit.GetLimitListener(req.Protocol) 45 if lis == nil { 46 return nil, errors.New("not found the protocol") 47 } 48 49 var resp = ConnCountResp{ 50 Protocol: req.Protocol, 51 Total: lis.GetListenerConnCount(), 52 Host: map[string]int32{}, 53 } 54 if req.Host != "" { 55 resp.Host[req.Host] = lis.GetHostConnCount(req.Host) 56 } else { 57 lis.Range(func(host string, count int32) bool { 58 resp.Host[host] = count 59 return true 60 }) 61 } 62 63 return &resp, nil 64 } 65 66 func (s *Server) GetServerConnStats(_ context.Context, req *ConnReq) (*ConnStatsResp, error) { 67 if req.Protocol == "" { 68 return nil, errors.New("missing param protocol") 69 } 70 71 lis := connlimit.GetLimitListener(req.Protocol) 72 if lis == nil { 73 return nil, errors.New("not found the protocol") 74 } 75 76 var resp ConnStatsResp 77 78 resp.Protocol = req.Protocol 79 resp.ActiveConnTotal = lis.GetListenerConnCount() 80 81 stats := lis.GetHostConnStats(req.Host) 82 resp.StatsTotal = len(stats) 83 84 // 过滤amount 85 if req.Amount > 0 { 86 for _, stat := range stats { 87 if stat.Amount >= int32(req.Amount) { 88 resp.Stats = append(resp.Stats, stat) 89 } 90 } 91 } else { 92 resp.Stats = stats 93 } 94 95 resp.StatsSize = len(resp.Stats) 96 if len(resp.Stats) == 0 { 97 resp.Stats = make([]*connlimit.HostConnStat, 0) 98 } 99 100 return &resp, nil 101 } 102 103 func (s *Server) CloseConnections(_ context.Context, reqs []ConnReq) error { 104 for _, entry := range reqs { 105 listener := connlimit.GetLimitListener(entry.Protocol) 106 if listener == nil { 107 log.Warnf("[MAINTAIN] not found listener for protocol(%s)", entry.Protocol) 108 continue 109 } 110 111 if entry.Port != 0 { 112 if conn := listener.GetHostConnection(entry.Host, entry.Port); conn != nil { 113 log.Infof("[MAINTAIN] address(%s:%d) to be closed", entry.Host, entry.Port) 114 _ = conn.Close() 115 continue 116 } 117 } 118 119 log.Infof("[MAINTAIN] host(%s) connections to be closed", entry.Host) 120 activeConns := listener.GetHostActiveConns(entry.Host) 121 for k := range activeConns { 122 if activeConns[k] != nil { 123 _ = activeConns[k].Close() 124 } 125 } 126 } 127 128 return nil 129 } 130 131 func (s *Server) FreeOSMemory(_ context.Context) error { 132 log.Info("[MAINTAIN] start doing free os memory") 133 // 防止并发释放 134 start := time.Now() 135 s.mu.Lock() 136 debug.FreeOSMemory() 137 s.mu.Unlock() 138 log.Infof("[MAINTAIN] finish doing free os memory, used time: %v", time.Since(start)) 139 return nil 140 } 141 142 func (s *Server) CleanInstance(ctx context.Context, req *apiservice.Instance) *apiservice.Response { 143 getInstanceID := func() (string, *apiservice.Response) { 144 if req.GetId() != nil { 145 if req.GetId().GetValue() == "" { 146 return "", api.NewInstanceResponse(apimodel.Code_InvalidInstanceID, req) 147 } 148 return req.GetId().GetValue(), nil 149 } 150 return utils.CheckInstanceTetrad(req) 151 } 152 153 instanceID, resp := getInstanceID() 154 if resp != nil { 155 return resp 156 } 157 if err := s.storage.CleanInstance(instanceID); err != nil { 158 log.Error("Clean instance", 159 zap.String("err", err.Error()), utils.ZapRequestID(utils.ParseRequestID(ctx))) 160 return api.NewInstanceResponse(commonstore.StoreCode2APICode(err), req) 161 } 162 163 log.Info("Clean instance", utils.ZapRequestID(utils.ParseRequestID(ctx)), utils.ZapInstanceID(instanceID)) 164 return api.NewInstanceResponse(apimodel.Code_ExecuteSuccess, req) 165 } 166 167 func (s *Server) BatchCleanInstances(ctx context.Context, batchSize uint32) (uint32, error) { 168 return s.storage.BatchCleanDeletedInstances(10*time.Minute, batchSize) 169 } 170 171 func (s *Server) GetLastHeartbeat(_ context.Context, req *apiservice.Instance) *apiservice.Response { 172 return s.healthCheckServer.GetLastHeartbeat(req) 173 } 174 175 func (s *Server) GetLogOutputLevel(_ context.Context) ([]ScopeLevel, error) { 176 scopes := commonlog.Scopes() 177 out := make([]ScopeLevel, 0, len(scopes)) 178 for k := range scopes { 179 out = append(out, ScopeLevel{ 180 Name: k, 181 Level: scopes[k].GetOutputLevel().Name(), 182 }) 183 } 184 185 return out, nil 186 } 187 188 func (s *Server) SetLogOutputLevel(_ context.Context, scope string, level string) error { 189 return commonlog.SetLogOutputLevel(scope, level) 190 } 191 192 func (s *Server) ListLeaderElections(_ context.Context) ([]*model.LeaderElection, error) { 193 return s.storage.ListLeaderElections() 194 } 195 196 func (s *Server) ReleaseLeaderElection(_ context.Context, electKey string) error { 197 return s.storage.ReleaseLeaderElection(electKey) 198 199 } 200 201 func (svr *Server) GetCMDBInfo(ctx context.Context) ([]model.LocationView, error) { 202 cmdb := plugin.GetCMDB() 203 if cmdb == nil { 204 return []model.LocationView{}, nil 205 } 206 207 ret := make([]model.LocationView, 0, 32) 208 _ = cmdb.Range(func(host string, location *model.Location) (bool, error) { 209 ret = append(ret, model.LocationView{ 210 IP: host, 211 Region: location.Proto.GetRegion().GetValue(), 212 Zone: location.Proto.GetZone().GetValue(), 213 Campus: location.Proto.GetCampus().GetValue(), 214 RegionID: location.RegionID, 215 ZoneID: location.ZoneID, 216 CampusID: location.CampusID, 217 }) 218 return true, nil 219 }) 220 221 return ret, nil 222 }