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 }