github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/framework/grpc/server.go (about)

     1  package ddgrpc
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"github.com/olekukonko/tablewriter"
     7  	"github.com/unionj-cloud/go-doudou/framework/internal/banner"
     8  	"github.com/unionj-cloud/go-doudou/framework/internal/config"
     9  	"github.com/unionj-cloud/go-doudou/toolkit/cast"
    10  	"github.com/unionj-cloud/go-doudou/toolkit/timeutils"
    11  	logger "github.com/unionj-cloud/go-doudou/toolkit/zlogger"
    12  	"google.golang.org/grpc"
    13  	"google.golang.org/grpc/reflection"
    14  	"net"
    15  	"os"
    16  	"os/signal"
    17  	"strings"
    18  	"time"
    19  )
    20  
    21  var startAt time.Time
    22  
    23  func init() {
    24  	startAt = time.Now()
    25  }
    26  
    27  type GrpcServer struct {
    28  	*grpc.Server
    29  }
    30  
    31  func NewGrpcServer(opt ...grpc.ServerOption) *GrpcServer {
    32  	server := GrpcServer{}
    33  	server.Server = grpc.NewServer(opt...)
    34  	return &server
    35  }
    36  
    37  func (srv *GrpcServer) printServices() {
    38  	if !config.CheckDev() {
    39  		return
    40  	}
    41  	logger.Info().Msg("================ Registered Services ================")
    42  	data := [][]string{}
    43  	for k, v := range srv.GetServiceInfo() {
    44  		for i, method := range v.Methods {
    45  			if i == 0 {
    46  				data = append(data, []string{k, method.Name})
    47  			} else {
    48  				data = append(data, []string{"", method.Name})
    49  			}
    50  		}
    51  	}
    52  
    53  	tableString := &strings.Builder{}
    54  	table := tablewriter.NewWriter(tableString)
    55  	table.SetHeader([]string{"SERVICE", "RPC"})
    56  	for _, v := range data {
    57  		table.Append(v)
    58  	}
    59  	table.Render() // Send output
    60  	rows := strings.Split(strings.TrimSpace(tableString.String()), "\n")
    61  	for _, row := range rows {
    62  		logger.Info().Msg(row)
    63  	}
    64  	logger.Info().Msg("===================================================")
    65  }
    66  
    67  // Run runs grpc server
    68  func (srv *GrpcServer) Run() {
    69  	banner.Print()
    70  	port := config.DefaultGddGrpcPort
    71  	if p, err := cast.ToIntE(config.GddGrpcPort.Load()); err == nil {
    72  		port = p
    73  	}
    74  	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
    75  	if err != nil {
    76  		logger.Panic().Msgf("failed to listen: %v", err)
    77  	}
    78  	reflection.Register(srv)
    79  	srv.printServices()
    80  	go func() {
    81  		logger.Info().Msgf("Grpc server is listening at %v", lis.Addr())
    82  		logger.Info().Msgf("Grpc server started in %s", time.Since(startAt))
    83  		if err := srv.Serve(lis); err != nil {
    84  			logger.Error().Msgf("failed to serve: %v", err)
    85  		}
    86  	}()
    87  
    88  	defer func() {
    89  		grace, err := time.ParseDuration(config.GddGraceTimeout.Load())
    90  		if err != nil {
    91  			logger.Debug().Msgf("Parse %s %s as time.Duration failed: %s, use default %s instead.\n", string(config.GddGraceTimeout),
    92  				config.GddGraceTimeout.Load(), err.Error(), config.DefaultGddGraceTimeout)
    93  			grace, _ = time.ParseDuration(config.DefaultGddGraceTimeout)
    94  		}
    95  		logger.Info().Msgf("Grpc server is gracefully shutting down in %s", grace)
    96  
    97  		ctx, cancel := context.WithTimeout(context.Background(), grace)
    98  		defer cancel()
    99  		if err := timeutils.CallWithCtx(ctx, func() struct{} {
   100  			srv.GracefulStop()
   101  			return struct{}{}
   102  		}); err != nil {
   103  			logger.Error().Err(err).Msg("")
   104  		}
   105  	}()
   106  
   107  	c := make(chan os.Signal, 1)
   108  	// We'll accept graceful shutdowns when quit via SIGINT (Ctrl+C)
   109  	// SIGKILL, SIGQUIT or SIGTERM (Ctrl+/) will not be caught.
   110  	signal.Notify(c, os.Interrupt)
   111  
   112  	// Block until we receive our signal.
   113  	<-c
   114  }