github.com/cloudwego/kitex@v0.9.0/internal/client/option.go (about) 1 /* 2 * Copyright 2021 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package client defines the Options of client 18 package client 19 20 import ( 21 "context" 22 "time" 23 24 "github.com/cloudwego/localsession/backup" 25 26 "github.com/cloudwego/kitex/internal/configutil" 27 "github.com/cloudwego/kitex/internal/stream" 28 "github.com/cloudwego/kitex/pkg/acl" 29 "github.com/cloudwego/kitex/pkg/circuitbreak" 30 connpool2 "github.com/cloudwego/kitex/pkg/connpool" 31 "github.com/cloudwego/kitex/pkg/diagnosis" 32 "github.com/cloudwego/kitex/pkg/discovery" 33 "github.com/cloudwego/kitex/pkg/endpoint" 34 "github.com/cloudwego/kitex/pkg/event" 35 "github.com/cloudwego/kitex/pkg/fallback" 36 "github.com/cloudwego/kitex/pkg/http" 37 "github.com/cloudwego/kitex/pkg/loadbalance" 38 "github.com/cloudwego/kitex/pkg/loadbalance/lbcache" 39 "github.com/cloudwego/kitex/pkg/proxy" 40 "github.com/cloudwego/kitex/pkg/remote" 41 "github.com/cloudwego/kitex/pkg/remote/codec/protobuf" 42 "github.com/cloudwego/kitex/pkg/remote/codec/thrift" 43 "github.com/cloudwego/kitex/pkg/remote/connpool" 44 "github.com/cloudwego/kitex/pkg/remote/trans/nphttp2" 45 "github.com/cloudwego/kitex/pkg/remote/trans/nphttp2/grpc" 46 "github.com/cloudwego/kitex/pkg/retry" 47 "github.com/cloudwego/kitex/pkg/rpcinfo" 48 "github.com/cloudwego/kitex/pkg/serviceinfo" 49 "github.com/cloudwego/kitex/pkg/stats" 50 "github.com/cloudwego/kitex/pkg/transmeta" 51 "github.com/cloudwego/kitex/pkg/utils" 52 "github.com/cloudwego/kitex/pkg/warmup" 53 "github.com/cloudwego/kitex/transport" 54 ) 55 56 func init() { 57 remote.PutPayloadCode(serviceinfo.Thrift, thrift.NewThriftCodec()) 58 remote.PutPayloadCode(serviceinfo.Protobuf, protobuf.NewProtobufCodec()) 59 } 60 61 // Options is used to initialize a client. 62 type Options struct { 63 Cli *rpcinfo.EndpointBasicInfo 64 Svr *rpcinfo.EndpointBasicInfo 65 Configs rpcinfo.RPCConfig 66 Locks *ConfigLocks 67 Once *configutil.OptionOnce 68 69 MetaHandlers []remote.MetaHandler 70 71 RemoteOpt *remote.ClientOption 72 Proxy proxy.ForwardProxy 73 Resolver discovery.Resolver 74 HTTPResolver http.Resolver 75 Balancer loadbalance.Loadbalancer 76 BalancerCacheOpt *lbcache.Options 77 PoolCfg *connpool2.IdleConfig 78 ErrHandle func(context.Context, error) error 79 Targets string 80 CBSuite *circuitbreak.CBSuite 81 Timeouts rpcinfo.TimeoutProvider 82 83 ACLRules []acl.RejectFunc 84 85 MWBs []endpoint.MiddlewareBuilder 86 IMWBs []endpoint.MiddlewareBuilder 87 88 Bus event.Bus 89 Events event.Queue 90 ExtraTimeout time.Duration 91 92 // DebugInfo should only contain objects that are suitable for json serialization. 93 DebugInfo utils.Slice 94 DebugService diagnosis.Service 95 96 // Observability 97 TracerCtl *rpcinfo.TraceController 98 StatsLevel *stats.Level 99 100 // retry policy 101 RetryMethodPolicies map[string]retry.Policy 102 RetryContainer *retry.Container 103 RetryWithResult *retry.ShouldResultRetry 104 105 // fallback policy 106 Fallback *fallback.Policy 107 108 CloseCallbacks []func() error 109 WarmUpOption *warmup.ClientOption 110 111 // GRPC 112 GRPCConnPoolSize uint32 113 GRPCConnectOpts *grpc.ConnectOptions 114 115 // XDS 116 XDSEnabled bool 117 XDSRouterMiddleware endpoint.Middleware 118 119 // Context backup 120 CtxBackupHandler backup.BackupHandler 121 122 Streaming stream.StreamingConfig 123 } 124 125 // Apply applies all options. 126 func (o *Options) Apply(opts []Option) { 127 for _, op := range opts { 128 op.F(o, &o.DebugInfo) 129 } 130 } 131 132 // Option is the only way to config client. 133 type Option struct { 134 F func(o *Options, di *utils.Slice) 135 } 136 137 // NewOptions creates a new option. 138 func NewOptions(opts []Option) *Options { 139 o := &Options{ 140 Cli: &rpcinfo.EndpointBasicInfo{Tags: make(map[string]string)}, 141 Svr: &rpcinfo.EndpointBasicInfo{Tags: make(map[string]string)}, 142 MetaHandlers: []remote.MetaHandler{transmeta.MetainfoClientHandler}, 143 RemoteOpt: newClientRemoteOption(), 144 Configs: rpcinfo.NewRPCConfig(), 145 Locks: NewConfigLocks(), 146 Once: configutil.NewOptionOnce(), 147 HTTPResolver: http.NewDefaultResolver(), 148 DebugService: diagnosis.NoopService, 149 150 Bus: event.NewEventBus(), 151 Events: event.NewQueue(event.MaxEventNum), 152 153 TracerCtl: &rpcinfo.TraceController{}, 154 155 GRPCConnectOpts: new(grpc.ConnectOptions), 156 } 157 o.Apply(opts) 158 159 o.initRemoteOpt() 160 161 if o.RetryContainer != nil && o.DebugService != nil { 162 o.DebugService.RegisterProbeFunc(diagnosis.RetryPolicyKey, o.RetryContainer.Dump) 163 } 164 165 if o.StatsLevel == nil { 166 level := stats.LevelDisabled 167 if o.TracerCtl.HasTracer() { 168 level = stats.LevelDetailed 169 } 170 o.StatsLevel = &level 171 } 172 return o 173 } 174 175 func (o *Options) initRemoteOpt() { 176 var zero connpool2.IdleConfig 177 178 if o.Configs.TransportProtocol()&transport.GRPC == transport.GRPC { 179 if o.PoolCfg != nil && *o.PoolCfg == zero { 180 // grpc unary short connection 181 o.GRPCConnectOpts.ShortConn = true 182 } 183 o.RemoteOpt.ConnPool = nphttp2.NewConnPool(o.Svr.ServiceName, o.GRPCConnPoolSize, *o.GRPCConnectOpts) 184 o.RemoteOpt.CliHandlerFactory = nphttp2.NewCliTransHandlerFactory() 185 } 186 if o.RemoteOpt.ConnPool == nil { 187 if o.PoolCfg != nil { 188 if *o.PoolCfg == zero { 189 o.RemoteOpt.ConnPool = connpool.NewShortPool(o.Svr.ServiceName) 190 } else { 191 o.RemoteOpt.ConnPool = connpool.NewLongPool(o.Svr.ServiceName, *o.PoolCfg) 192 } 193 } else { 194 o.RemoteOpt.ConnPool = connpool.NewLongPool( 195 o.Svr.ServiceName, 196 connpool2.IdleConfig{ 197 MaxIdlePerAddress: 10, 198 MaxIdleGlobal: 100, 199 MaxIdleTimeout: time.Minute, 200 }, 201 ) 202 } 203 } 204 } 205 206 // InitRetryContainer init retry container and add close callback 207 func (o *Options) InitRetryContainer() { 208 if o.RetryContainer == nil { 209 o.RetryContainer = retry.NewRetryContainerWithPercentageLimit() 210 o.CloseCallbacks = append(o.CloseCallbacks, o.RetryContainer.Close) 211 } 212 }