github.com/polarismesh/polaris@v1.17.8/test/benchmark/grpc/heartbeat/script.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 main
    19  
    20  import (
    21  	"bytes"
    22  	"context"
    23  	"fmt"
    24  	"io"
    25  	"log"
    26  	"net/http"
    27  	"os"
    28  	"os/signal"
    29  	"strconv"
    30  	"strings"
    31  	"syscall"
    32  	"time"
    33  
    34  	"github.com/golang/protobuf/jsonpb"
    35  	"github.com/polarismesh/specification/source/go/api/v1/model"
    36  	"github.com/polarismesh/specification/source/go/api/v1/service_manage"
    37  	"github.com/prometheus/client_golang/prometheus"
    38  	"github.com/prometheus/client_golang/prometheus/promhttp"
    39  	"google.golang.org/grpc"
    40  	"google.golang.org/protobuf/types/known/wrapperspb"
    41  )
    42  
    43  var (
    44  	// ServerAddr 北极星服务端接入地址IP,默认为 127.0.0.1
    45  	ServerAddr = os.Getenv("SERVER_IP")
    46  	// GRPCPort 北极星服务端接入地址 GRPC 协议端口,默认为 8091
    47  	GRPCPort, _ = strconv.ParseInt(os.Getenv("SERVER_PORT"), 10, 64)
    48  	// HttpPort 北极星服务端接入地址 HTTP 协议端口,默认为 8090
    49  	HttpPort, _ = strconv.ParseInt(os.Getenv("SERVER_PORT"), 10, 64)
    50  	// RunMode 运行模式,内容为 VERIFY(验证模式)/BENCHMARK(压测模式)
    51  	RunMode = os.Getenv("RUN_MODE")
    52  	// Service 服务名
    53  	Service = os.Getenv("SERVICE")
    54  	// Namespace 命名空间
    55  	Namespace = os.Getenv("NAMESPACE")
    56  	// BasePort 端口起始
    57  	BasePort, _ = strconv.ParseInt(os.Getenv("BASE_PORT"), 10, 64)
    58  	// PortNum 单个 POD 注册多少个端口
    59  	PortNum, _ = strconv.ParseInt(os.Getenv("PORT_NUM"), 10, 64)
    60  	// BeatInterval 心跳默认周期, 单位为秒
    61  	BeatInterval, _ = strconv.ParseInt(os.Getenv("BEAT_INTERVAL"), 10, 64)
    62  	// CheckInterval 检查任务执行周期
    63  	CheckInterval, _ = time.ParseDuration(os.Getenv("CHECK_INTERVAL"))
    64  	// PodIP 实例注册 IP
    65  	PodIP = os.Getenv("POD_IP")
    66  	// metricsRegistry .
    67  	metricsRegistry = prometheus.NewRegistry()
    68  	// heartbeatCount 客户端心跳上报次数
    69  	heartbeatCount = prometheus.NewCounter(prometheus.CounterOpts{
    70  		Name: "client_beat_count",
    71  	})
    72  )
    73  
    74  const (
    75  	defaultSeverIP       = "127.0.0.1"
    76  	defaultGrpcPort      = 8091
    77  	defaultHttpPort      = 8090
    78  	defaultBeatInterval  = 5
    79  	defaultBasePort      = 8080
    80  	defaultPortNum       = 1
    81  	defaultService       = "benchmark-heartbeat"
    82  	defaultNamesapce     = "benchmark"
    83  	metricsPort          = 9090
    84  	defaultCheckInterval = time.Minute
    85  )
    86  
    87  func setDefault() {
    88  	if ServerAddr == "" {
    89  		ServerAddr = defaultSeverIP
    90  	}
    91  	if GRPCPort == 0 {
    92  		GRPCPort = defaultGrpcPort
    93  	}
    94  	if HttpPort == 0 {
    95  		HttpPort = defaultHttpPort
    96  	}
    97  	if Service == "" {
    98  		Service = defaultService
    99  	}
   100  	if Namespace == "" {
   101  		Namespace = defaultNamesapce
   102  	}
   103  	if BasePort == 0 {
   104  		BasePort = defaultBasePort
   105  	}
   106  	if PortNum == 0 {
   107  		PortNum = 1
   108  	}
   109  	if CheckInterval == 0 {
   110  		CheckInterval = defaultCheckInterval
   111  	}
   112  	log.Printf("run_mode(%s)", RunMode)
   113  	log.Printf("server_addr(%s)", ServerAddr)
   114  	log.Printf("grpc_port(%d)", GRPCPort)
   115  	log.Printf("http_port(%d)", HttpPort)
   116  	log.Printf("namespace(%s)", Namespace)
   117  	log.Printf("service(%s)", Service)
   118  	log.Printf("base_port(%d)", BasePort)
   119  	log.Printf("port_num(%d)", PortNum)
   120  	log.Printf("check_interval(%v)", CheckInterval)
   121  }
   122  
   123  func setMetrics() {
   124  	_ = metricsRegistry.Register(heartbeatCount)
   125  }
   126  
   127  func main() {
   128  	setDefault()
   129  	setMetrics()
   130  	switch strings.ToLower(RunMode) {
   131  	case "verify":
   132  		go runVerifyMode()
   133  	case "benchmark":
   134  		go runBenchmarkMode()
   135  	default:
   136  		panic("unknown run mode, please export RUN_MODE=verify or RUN_MODE=benchmark")
   137  	}
   138  	go func() {
   139  		_ = http.ListenAndServe(fmt.Sprintf("0.0.0.0:%d", metricsPort),
   140  			promhttp.HandlerFor(metricsRegistry, promhttp.HandlerOpts{EnableOpenMetrics: true}))
   141  	}()
   142  	mainLoop()
   143  }
   144  
   145  func runVerifyMode() {
   146  	ticker := time.NewTicker(CheckInterval)
   147  
   148  	checkInstanceHealth := func() {
   149  		req := &service_manage.DiscoverRequest{
   150  			Type: service_manage.DiscoverRequest_INSTANCE,
   151  			Service: &service_manage.Service{
   152  				Namespace: wrapperspb.String(Namespace),
   153  				Name:      wrapperspb.String(Service),
   154  			},
   155  		}
   156  
   157  		marshaler := jsonpb.Marshaler{}
   158  		body, _ := marshaler.MarshalToString(req)
   159  		rsp, err := http.Post(fmt.Sprintf("http://%s:%d/v1/Discover", ServerAddr, HttpPort), "application/json", bytes.NewBufferString(body))
   160  		if err != nil {
   161  			log.Printf("[ERROR] send discover to server fail: %s", err.Error())
   162  			return
   163  		}
   164  
   165  		defer func() {
   166  			_ = rsp.Body.Close()
   167  		}()
   168  		data, _ := io.ReadAll(rsp.Body)
   169  		discoverRsp := &service_manage.DiscoverResponse{}
   170  		if err := jsonpb.Unmarshal(bytes.NewBuffer(data), discoverRsp); err != nil {
   171  			log.Printf("[ERROR] unmarshaler discover resp fail: %s", err.Error())
   172  			return
   173  		}
   174  		if discoverRsp.GetCode().GetValue() != uint32(model.Code_ExecuteSuccess) {
   175  			log.Printf("[ERROR] receive discover resp fail: %s", discoverRsp.GetInfo().GetValue())
   176  			return
   177  		}
   178  		// 检查实例健康状态
   179  	}
   180  
   181  	checkInstanceBeatTimestamp := func() {
   182  
   183  	}
   184  
   185  	for {
   186  		select {
   187  		case <-ticker.C:
   188  			checkInstanceHealth()
   189  			checkInstanceBeatTimestamp()
   190  		}
   191  	}
   192  }
   193  
   194  func runBenchmarkMode() {
   195  	conn, err := grpc.DialContext(context.Background(), fmt.Sprintf("%s:%d", ServerAddr, GRPCPort),
   196  		grpc.WithBlock(),
   197  		grpc.WithInsecure(),
   198  	)
   199  	if err != nil {
   200  		panic(err)
   201  	}
   202  
   203  	client := service_manage.NewPolarisGRPCClient(conn)
   204  
   205  	// 先注册
   206  	for i := 0; i < int(PortNum); i++ {
   207  		instance := &service_manage.Instance{
   208  			Namespace:         wrapperspb.String(Namespace),
   209  			Service:           wrapperspb.String(Service),
   210  			Host:              wrapperspb.String(PodIP),
   211  			Port:              wrapperspb.UInt32(uint32(int(BasePort) + i)),
   212  			EnableHealthCheck: wrapperspb.Bool(true),
   213  			HealthCheck: &service_manage.HealthCheck{
   214  				Type: service_manage.HealthCheck_HEARTBEAT,
   215  				Heartbeat: &service_manage.HeartbeatHealthCheck{
   216  					Ttl: wrapperspb.UInt32(uint32(BeatInterval)),
   217  				},
   218  			},
   219  		}
   220  
   221  		resp, err := client.RegisterInstance(context.Background(), instance)
   222  		if err != nil {
   223  			panic(err)
   224  		}
   225  		if resp.GetCode().GetValue() != uint32(model.Code_ExecuteSuccess) {
   226  			panic(resp.GetInfo().GetValue())
   227  		}
   228  		log.Printf("[INFO] instance register success id: %s", instance.GetId().GetValue())
   229  		instance.Id = resp.GetInstance().GetId()
   230  		go func(instance *service_manage.Instance) {
   231  			ticker := time.NewTicker(time.Duration(BeatInterval) * time.Second)
   232  			defer ticker.Stop()
   233  
   234  			for range ticker.C {
   235  				heartbeatCount.Inc()
   236  				resp, err := client.Heartbeat(context.Background(), instance)
   237  				if err != nil {
   238  					log.Printf("[ERROR] instance(%s) beat fail error: %s", instance.GetId().GetValue(), err.Error())
   239  				}
   240  				if resp.GetCode().GetValue() != uint32(model.Code_ExecuteSuccess) {
   241  					log.Printf("[ERROR] instance(%s) beat fail info: %s", instance.GetId().GetValue(), resp.GetInfo().GetValue())
   242  				}
   243  			}
   244  		}(instance)
   245  	}
   246  
   247  	// 发起任务开始定期 心跳上报
   248  }
   249  
   250  // mainLoop 等待信号量执行退出
   251  func mainLoop() {
   252  	ch := make(chan os.Signal, 1)
   253  
   254  	// 监听信号量
   255  	signal.Notify(ch, []os.Signal{
   256  		syscall.SIGINT, syscall.SIGTERM,
   257  		syscall.SIGSEGV, syscall.SIGUSR1, syscall.SIGUSR2,
   258  	}...)
   259  
   260  	for {
   261  		select {
   262  		case <-ch:
   263  			log.Printf("[INFO] catch signal, stop benchmark server")
   264  			return
   265  		}
   266  	}
   267  }