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 }