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  }