trpc.group/trpc-go/trpc-go@v1.0.3/trpc.go (about)

     1  //
     2  //
     3  // Tencent is pleased to support the open source community by making tRPC available.
     4  //
     5  // Copyright (C) 2023 THL A29 Limited, a Tencent company.
     6  // All rights reserved.
     7  //
     8  // If you have downloaded a copy of the tRPC source code from Tencent,
     9  // please note that tRPC source code is licensed under the  Apache 2.0 License,
    10  // A copy of the Apache 2.0 License is included in this file.
    11  //
    12  //
    13  
    14  // Package trpc is the Go implementation of tRPC, which is designed to be high-performance,
    15  // everything-pluggable and easy for testing.
    16  package trpc
    17  
    18  import (
    19  	"errors"
    20  	"fmt"
    21  
    22  	"trpc.group/trpc-go/trpc-go/admin"
    23  	"trpc.group/trpc-go/trpc-go/filter"
    24  	"trpc.group/trpc-go/trpc-go/log"
    25  	"trpc.group/trpc-go/trpc-go/naming/registry"
    26  	"trpc.group/trpc-go/trpc-go/rpcz"
    27  	"trpc.group/trpc-go/trpc-go/server"
    28  	"trpc.group/trpc-go/trpc-go/transport"
    29  
    30  	"go.uber.org/automaxprocs/maxprocs"
    31  )
    32  
    33  // NewServer parses the yaml config file to quickly start the server with multiple services.
    34  // The config file is ./trpc_go.yaml by default and can be set by the flag -conf.
    35  // This method should be called only once.
    36  func NewServer(opt ...server.Option) *server.Server {
    37  	// load and parse config file
    38  	cfg, err := LoadConfig(serverConfigPath())
    39  	if err != nil {
    40  		panic("load config fail: " + err.Error())
    41  	}
    42  
    43  	// set to global config for other plugins' accessing to the config
    44  	SetGlobalConfig(cfg)
    45  
    46  	closePlugins, err := SetupPlugins(cfg.Plugins)
    47  	if err != nil {
    48  		panic("setup plugin fail: " + err.Error())
    49  	}
    50  	if err := SetupClients(&cfg.Client); err != nil {
    51  		panic("failed to setup client: " + err.Error())
    52  	}
    53  
    54  	// set default GOMAXPROCS for docker
    55  	maxprocs.Set(maxprocs.Logger(log.Debugf))
    56  	s := NewServerWithConfig(cfg, opt...)
    57  	s.RegisterOnShutdown(func() {
    58  		if err := closePlugins(); err != nil {
    59  			log.Errorf("failed to close plugins, err: %s", err)
    60  		}
    61  	})
    62  	return s
    63  }
    64  
    65  // NewServerWithConfig initializes a server with a Config.
    66  // If yaml config file not used, custom Config parsing is needed to pass the Config into this function.
    67  // Plugins' setup is left to do if this method is called.
    68  func NewServerWithConfig(cfg *Config, opt ...server.Option) *server.Server {
    69  	// repair config
    70  	if err := RepairConfig(cfg); err != nil {
    71  		panic("repair config fail: " + err.Error())
    72  	}
    73  
    74  	// set to global Config
    75  	SetGlobalConfig(cfg)
    76  
    77  	s := &server.Server{
    78  		MaxCloseWaitTime: getMillisecond(cfg.Server.MaxCloseWaitTime),
    79  	}
    80  
    81  	// setup admin service
    82  	setupAdmin(s, cfg)
    83  
    84  	// init service one by one
    85  	for _, c := range cfg.Server.Service {
    86  		s.AddService(c.Name, newServiceWithConfig(cfg, c, opt...))
    87  	}
    88  	return s
    89  }
    90  
    91  // GetAdminService gets admin service from server.Server.
    92  func GetAdminService(s *server.Server) (*admin.Server, error) {
    93  	adminServer, ok := s.Service(admin.ServiceName).(*admin.Server)
    94  	if !ok {
    95  		return nil, errors.New("admin server may not be enabled")
    96  	}
    97  	return adminServer, nil
    98  }
    99  
   100  func setupAdmin(s *server.Server, cfg *Config) {
   101  	// admin configured, then admin service will be started
   102  	opts := []admin.Option{
   103  		admin.WithSkipServe(cfg.Server.Admin.Port == 0),
   104  		admin.WithVersion(Version()),
   105  		admin.WithTLS(cfg.Server.Admin.EnableTLS),
   106  		admin.WithConfigPath(ServerConfigPath),
   107  		admin.WithReadTimeout(getMillisecond(cfg.Server.Admin.ReadTimeout)),
   108  		admin.WithWriteTimeout(getMillisecond(cfg.Server.Admin.WriteTimeout)),
   109  	}
   110  	if cfg.Server.Admin.Port > 0 {
   111  		opts = append(opts, admin.WithAddr(fmt.Sprintf("%s:%d", cfg.Server.Admin.IP, cfg.Server.Admin.Port)))
   112  	}
   113  	if cfg.Server.Admin.RPCZ != nil {
   114  		rpcz.GlobalRPCZ = rpcz.NewRPCZ(cfg.Server.Admin.RPCZ.generate())
   115  	}
   116  	s.AddService(admin.ServiceName, admin.NewServer(opts...))
   117  }
   118  
   119  func newServiceWithConfig(cfg *Config, serviceCfg *ServiceConfig, opt ...server.Option) server.Service {
   120  	var (
   121  		filters     filter.ServerChain
   122  		filterNames []string
   123  	)
   124  	// Global filter is at front and is deduplicated.
   125  	for _, name := range deduplicate(cfg.Server.Filter, serviceCfg.Filter) {
   126  		f := filter.GetServer(name)
   127  		if f == nil {
   128  			panic(fmt.Sprintf("filter %s no registered, do not configure", name))
   129  		}
   130  		filters = append(filters, f)
   131  		filterNames = append(filterNames, name)
   132  	}
   133  	filterNames = append(filterNames, "fixTimeout")
   134  
   135  	var streamFilter []server.StreamFilter
   136  	for _, name := range deduplicate(cfg.Server.StreamFilter, serviceCfg.StreamFilter) {
   137  		f := server.GetStreamFilter(name)
   138  		if f == nil {
   139  			panic(fmt.Sprintf("stream filter %s no registered, do not configure", name))
   140  		}
   141  		streamFilter = append(streamFilter, f)
   142  	}
   143  
   144  	// get registry by service
   145  	reg := registry.Get(serviceCfg.Name)
   146  	if serviceCfg.Registry != "" && reg == nil {
   147  		log.Warnf("service:%s registry not exist", serviceCfg.Name)
   148  	}
   149  
   150  	opts := []server.Option{
   151  		server.WithNamespace(cfg.Global.Namespace),
   152  		server.WithEnvName(cfg.Global.EnvName),
   153  		server.WithContainer(cfg.Global.ContainerName),
   154  		server.WithServiceName(serviceCfg.Name),
   155  		server.WithProtocol(serviceCfg.Protocol),
   156  		server.WithTransport(transport.GetServerTransport(serviceCfg.Transport)),
   157  		server.WithNetwork(serviceCfg.Network),
   158  		server.WithAddress(serviceCfg.Address),
   159  		server.WithStreamFilters(streamFilter...),
   160  		server.WithRegistry(reg),
   161  		server.WithTimeout(getMillisecond(serviceCfg.Timeout)),
   162  		server.WithDisableRequestTimeout(serviceCfg.DisableRequestTimeout),
   163  		server.WithDisableKeepAlives(serviceCfg.DisableKeepAlives),
   164  		server.WithCloseWaitTime(getMillisecond(cfg.Server.CloseWaitTime)),
   165  		server.WithMaxCloseWaitTime(getMillisecond(cfg.Server.MaxCloseWaitTime)),
   166  		server.WithIdleTimeout(getMillisecond(serviceCfg.Idletime)),
   167  		server.WithTLS(serviceCfg.TLSCert, serviceCfg.TLSKey, serviceCfg.CACert),
   168  		server.WithServerAsync(*serviceCfg.ServerAsync),
   169  		server.WithMaxRoutines(serviceCfg.MaxRoutines),
   170  		server.WithWritev(*serviceCfg.Writev),
   171  	}
   172  	for i := range filters {
   173  		opts = append(opts, server.WithNamedFilter(filterNames[i], filters[i]))
   174  	}
   175  
   176  	if cfg.Global.EnableSet == "Y" {
   177  		opts = append(opts, server.WithSetName(cfg.Global.FullSetName))
   178  	}
   179  	opts = append(opts, opt...)
   180  	return server.New(opts...)
   181  }