gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/grpc/dialoptions.go (about) 1 /* 2 * 3 * Copyright 2018 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19 package grpc 20 21 import ( 22 "context" 23 "fmt" 24 "gitee.com/zhaochuninhefei/gmgo/grpc/encoding" 25 "net" 26 "time" 27 28 "gitee.com/zhaochuninhefei/gmgo/grpc/backoff" 29 "gitee.com/zhaochuninhefei/gmgo/grpc/balancer" 30 "gitee.com/zhaochuninhefei/gmgo/grpc/credentials" 31 "gitee.com/zhaochuninhefei/gmgo/grpc/credentials/insecure" 32 "gitee.com/zhaochuninhefei/gmgo/grpc/internal" 33 internalbackoff "gitee.com/zhaochuninhefei/gmgo/grpc/internal/backoff" 34 "gitee.com/zhaochuninhefei/gmgo/grpc/internal/transport" 35 "gitee.com/zhaochuninhefei/gmgo/grpc/keepalive" 36 "gitee.com/zhaochuninhefei/gmgo/grpc/resolver" 37 "gitee.com/zhaochuninhefei/gmgo/grpc/stats" 38 ) 39 40 // dialOptions configure a Dial call. dialOptions are set by the DialOption 41 // values passed to Dial. 42 type dialOptions struct { 43 unaryInt UnaryClientInterceptor 44 streamInt StreamClientInterceptor 45 46 chainUnaryInts []UnaryClientInterceptor 47 chainStreamInts []StreamClientInterceptor 48 49 cp Compressor 50 dc Decompressor 51 bs internalbackoff.Strategy 52 block bool 53 returnLastError bool 54 timeout time.Duration 55 scChan <-chan ServiceConfig 56 authority string 57 copts transport.ConnectOptions 58 callOptions []CallOption 59 // This is used by WithBalancerName dial option. 60 balancerBuilder balancer.Builder 61 channelzParentID int64 62 disableServiceConfig bool 63 disableRetry bool 64 disableHealthCheck bool 65 healthCheckFunc internal.HealthChecker 66 minConnectTimeout func() time.Duration 67 defaultServiceConfig *ServiceConfig // defaultServiceConfig is parsed from defaultServiceConfigRawJSON. 68 defaultServiceConfigRawJSON *string 69 resolvers []resolver.Builder 70 } 71 72 // DialOption configures how we set up the connection. 73 type DialOption interface { 74 apply(*dialOptions) 75 } 76 77 // EmptyDialOption does not alter the dial configuration. It can be embedded in 78 // another structure to build custom dial options. 79 // 80 // Experimental 81 // 82 // Notice: This type is EXPERIMENTAL and may be changed or removed in a 83 // later release. 84 type EmptyDialOption struct{} 85 86 func (EmptyDialOption) apply(*dialOptions) {} 87 88 // funcDialOption wraps a function that modifies dialOptions into an 89 // implementation of the DialOption interface. 90 type funcDialOption struct { 91 f func(*dialOptions) 92 } 93 94 func (fdo *funcDialOption) apply(do *dialOptions) { 95 fdo.f(do) 96 } 97 98 func newFuncDialOption(f func(*dialOptions)) *funcDialOption { 99 return &funcDialOption{ 100 f: f, 101 } 102 } 103 104 // WithWriteBufferSize determines how much data can be batched before doing a 105 // write on the wire. The corresponding memory allocation for this buffer will 106 // be twice the size to keep syscalls low. The default value for this buffer is 107 // 32KB. 108 // 109 // Zero will disable the write buffer such that each write will be on underlying 110 // connection. Note: A Send call may not directly translate to a write. 111 func WithWriteBufferSize(s int) DialOption { 112 return newFuncDialOption(func(o *dialOptions) { 113 o.copts.WriteBufferSize = s 114 }) 115 } 116 117 // WithReadBufferSize lets you set the size of read buffer, this determines how 118 // much data can be read at most for each read syscall. 119 // 120 // The default value for this buffer is 32KB. Zero will disable read buffer for 121 // a connection so data framer can access the underlying conn directly. 122 func WithReadBufferSize(s int) DialOption { 123 return newFuncDialOption(func(o *dialOptions) { 124 o.copts.ReadBufferSize = s 125 }) 126 } 127 128 // WithInitialWindowSize returns a DialOption which sets the value for initial 129 // window size on a stream. The lower bound for window size is 64K and any value 130 // smaller than that will be ignored. 131 func WithInitialWindowSize(s int32) DialOption { 132 return newFuncDialOption(func(o *dialOptions) { 133 o.copts.InitialWindowSize = s 134 }) 135 } 136 137 // WithInitialConnWindowSize returns a DialOption which sets the value for 138 // initial window size on a connection. The lower bound for window size is 64K 139 // and any value smaller than that will be ignored. 140 func WithInitialConnWindowSize(s int32) DialOption { 141 return newFuncDialOption(func(o *dialOptions) { 142 o.copts.InitialConnWindowSize = s 143 }) 144 } 145 146 // WithMaxMsgSize returns a DialOption which sets the maximum message size the 147 // client can receive. 148 // 149 // Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead. Will 150 // be supported throughout 1.x. 151 //goland:noinspection GoUnusedExportedFunction 152 func WithMaxMsgSize(s int) DialOption { 153 return WithDefaultCallOptions(MaxCallRecvMsgSize(s)) 154 } 155 156 // WithDefaultCallOptions returns a DialOption which sets the default 157 // CallOptions for calls over the connection. 158 func WithDefaultCallOptions(cos ...CallOption) DialOption { 159 return newFuncDialOption(func(o *dialOptions) { 160 o.callOptions = append(o.callOptions, cos...) 161 }) 162 } 163 164 // WithCodec returns a DialOption which sets a codec for message marshaling and 165 // unmarshaling. 166 // 167 // ToDeprecated: use WithDefaultCallOptions(ForceCodec(_)) instead. Will be 168 // supported throughout 1.x. 169 func WithCodec(c encoding.Codec) DialOption { 170 return WithDefaultCallOptions(CallCustomCodec(c)) 171 } 172 173 // WithCompressor returns a DialOption which sets a Compressor to use for 174 // message compression. It has lower priority than the compressor set by the 175 // UseCompressor CallOption. 176 // 177 // ToDeprecated: use UseCompressor instead. Will be supported throughout 1.x. 178 func WithCompressor(cp Compressor) DialOption { 179 return newFuncDialOption(func(o *dialOptions) { 180 o.cp = cp 181 }) 182 } 183 184 // WithDecompressor returns a DialOption which sets a Decompressor to use for 185 // incoming message decompression. If incoming response messages are encoded 186 // using the decompressor's Type(), it will be used. Otherwise, the message 187 // encoding will be used to look up the compressor registered via 188 // encoding.RegisterCompressor, which will then be used to decompress the 189 // message. If no compressor is registered for the encoding, an Unimplemented 190 // status error will be returned. 191 // 192 // ToDeprecated: use encoding.RegisterCompressor instead. Will be supported 193 // throughout 1.x. 194 func WithDecompressor(dc Decompressor) DialOption { 195 return newFuncDialOption(func(o *dialOptions) { 196 o.dc = dc 197 }) 198 } 199 200 // WithBalancerName sets the balancer that the ClientConn will be initialized 201 // with. Balancer registered with balancerName will be used. This function 202 // panics if no balancer was registered by balancerName. 203 // 204 // The balancer cannot be overridden by balancer option specified by service 205 // config. 206 // 207 // ToDeprecated: use WithDefaultServiceConfig and WithDisableServiceConfig 208 // instead. Will be removed in a future 1.x release. 209 func WithBalancerName(balancerName string) DialOption { 210 builder := balancer.Get(balancerName) 211 if builder == nil { 212 panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName)) 213 } 214 return newFuncDialOption(func(o *dialOptions) { 215 o.balancerBuilder = builder 216 }) 217 } 218 219 // WithServiceConfig returns a DialOption which has a channel to read the 220 // service configuration. 221 // 222 // ToDeprecated: service config should be received through name resolver or via 223 // WithDefaultServiceConfig, as specified at 224 // https://github.com/grpc/grpc/blob/master/doc/service_config.md. Will be 225 // removed in a future 1.x release. 226 func WithServiceConfig(c <-chan ServiceConfig) DialOption { 227 return newFuncDialOption(func(o *dialOptions) { 228 o.scChan = c 229 }) 230 } 231 232 // WithConnectParams configures the ClientConn to use the provided ConnectParams 233 // for creating and maintaining connections to servers. 234 // 235 // The backoff configuration specified as part of the ConnectParams overrides 236 // all defaults specified in 237 // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md. Consider 238 // using the backoff.DefaultConfig as a base, in cases where you want to 239 // override only a subset of the backoff configuration. 240 func WithConnectParams(p ConnectParams) DialOption { 241 return newFuncDialOption(func(o *dialOptions) { 242 o.bs = internalbackoff.Exponential{Config: p.Backoff} 243 o.minConnectTimeout = func() time.Duration { 244 return p.MinConnectTimeout 245 } 246 }) 247 } 248 249 // WithBackoffMaxDelay configures the dialer to use the provided maximum delay 250 // when backing off after failed connection attempts. 251 // 252 // ToDeprecated: use WithConnectParams instead. Will be supported throughout 1.x. 253 func WithBackoffMaxDelay(md time.Duration) DialOption { 254 return WithBackoffConfig(BackoffConfig{MaxDelay: md}) 255 } 256 257 // WithBackoffConfig configures the dialer to use the provided backoff 258 // parameters after connection failures. 259 // 260 // ToDeprecated: use WithConnectParams instead. Will be supported throughout 1.x. 261 func WithBackoffConfig(b BackoffConfig) DialOption { 262 bc := backoff.DefaultConfig 263 bc.MaxDelay = b.MaxDelay 264 return withBackoff(internalbackoff.Exponential{Config: bc}) 265 } 266 267 // withBackoff sets the backoff strategy used for connectRetryNum after a failed 268 // connection attempt. 269 // 270 // This can be exported if arbitrary backoff strategies are allowed by gRPC. 271 func withBackoff(bs internalbackoff.Strategy) DialOption { 272 return newFuncDialOption(func(o *dialOptions) { 273 o.bs = bs 274 }) 275 } 276 277 // WithBlock returns a DialOption which makes callers of Dial block until the 278 // underlying connection is up. Without this, Dial returns immediately and 279 // connecting the server happens in background. 280 func WithBlock() DialOption { 281 return newFuncDialOption(func(o *dialOptions) { 282 o.block = true 283 }) 284 } 285 286 // WithReturnConnectionError returns a DialOption which makes the client connection 287 // return a string containing both the last connection error that occurred and 288 // the context.DeadlineExceeded error. 289 // Implies WithBlock() 290 // 291 // Experimental 292 // 293 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 294 // later release. 295 func WithReturnConnectionError() DialOption { 296 return newFuncDialOption(func(o *dialOptions) { 297 o.block = true 298 o.returnLastError = true 299 }) 300 } 301 302 // WithInsecure returns a DialOption which disables transport security for this 303 // ClientConn. Under the hood, it uses insecure.NewCredentials(). 304 // 305 // Note that using this DialOption with per-RPC credentials (through 306 // WithCredentialsBundle or WithPerRPCCredentials) which require transport 307 // security is incompatible and will cause grpc.Dial() to fail. 308 // 309 // Deprecated: use WithTransportCredentials and insecure.NewCredentials() instead. 310 // Will be supported throughout 1.x. 311 func WithInsecure() DialOption { 312 return newFuncDialOption(func(o *dialOptions) { 313 o.copts.TransportCredentials = insecure.NewCredentials() 314 }) 315 } 316 317 // WithNoProxy returns a DialOption which disables the use of proxies for this 318 // ClientConn. This is ignored if WithDialer or WithContextDialer are used. 319 // 320 // Experimental 321 // 322 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 323 // later release. 324 //goland:noinspection GoUnusedExportedFunction 325 func WithNoProxy() DialOption { 326 return newFuncDialOption(func(o *dialOptions) { 327 o.copts.UseProxy = false 328 }) 329 } 330 331 // WithTransportCredentials returns a DialOption which configures a connection 332 // level security credentials (e.g., TLS/SSL). This should not be used together 333 // with WithCredentialsBundle. 334 func WithTransportCredentials(creds credentials.TransportCredentials) DialOption { 335 return newFuncDialOption(func(o *dialOptions) { 336 o.copts.TransportCredentials = creds 337 }) 338 } 339 340 // WithPerRPCCredentials returns a DialOption which sets credentials and places 341 // auth state on each outbound RPC. 342 func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption { 343 return newFuncDialOption(func(o *dialOptions) { 344 o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds) 345 }) 346 } 347 348 // WithCredentialsBundle returns a DialOption to set a credentials bundle for 349 // the ClientConn.WithCreds. This should not be used together with 350 // WithTransportCredentials. 351 // 352 // Experimental 353 // 354 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 355 // later release. 356 func WithCredentialsBundle(b credentials.Bundle) DialOption { 357 return newFuncDialOption(func(o *dialOptions) { 358 o.copts.CredsBundle = b 359 }) 360 } 361 362 // WithTimeout returns a DialOption that configures a timeout for dialing a 363 // ClientConn initially. This is valid if and only if WithBlock() is present. 364 // 365 // Deprecated: use DialContext instead of Dial and context.WithTimeout 366 // instead. Will be supported throughout 1.x. 367 func WithTimeout(d time.Duration) DialOption { 368 return newFuncDialOption(func(o *dialOptions) { 369 o.timeout = d 370 }) 371 } 372 373 // WithContextDialer returns a DialOption that sets a dialer to create 374 // connections. If FailOnNonTempDialError() is set to true, and an error is 375 // returned by f, gRPC checks the error's Temporary() method to decide if it 376 // should try to reconnect to the network address. 377 func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption { 378 return newFuncDialOption(func(o *dialOptions) { 379 o.copts.Dialer = f 380 }) 381 } 382 383 func init() { 384 internal.WithHealthCheckFunc = withHealthCheckFunc 385 } 386 387 // WithDialer returns a DialOption that specifies a function to use for dialing 388 // network addresses. If FailOnNonTempDialError() is set to true, and an error 389 // is returned by f, gRPC checks the error's Temporary() method to decide if it 390 // should try to reconnect to the network address. 391 // 392 // ToDeprecated: use WithContextDialer instead. Will be supported throughout 393 // 1.x. 394 func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption { 395 return WithContextDialer( 396 func(ctx context.Context, addr string) (net.Conn, error) { 397 if deadline, ok := ctx.Deadline(); ok { 398 return f(addr, time.Until(deadline)) 399 } 400 return f(addr, 0) 401 }) 402 } 403 404 // WithStatsHandler returns a DialOption that specifies the stats handler for 405 // all the RPCs and underlying network connections in this ClientConn. 406 func WithStatsHandler(h stats.Handler) DialOption { 407 return newFuncDialOption(func(o *dialOptions) { 408 o.copts.StatsHandler = h 409 }) 410 } 411 412 // FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on 413 // non-temporary dial errors. If f is true, and dialer returns a non-temporary 414 // error, gRPC will fail the connection to the network address and won't try to 415 // reconnect. The default value of FailOnNonTempDialError is false. 416 // 417 // FailOnNonTempDialError only affects the initial dial, and does not do 418 // anything useful unless you are also using WithBlock(). 419 // 420 // Experimental 421 // 422 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 423 // later release. 424 func FailOnNonTempDialError(f bool) DialOption { 425 return newFuncDialOption(func(o *dialOptions) { 426 o.copts.FailOnNonTempDialError = f 427 }) 428 } 429 430 // WithUserAgent returns a DialOption that specifies a user agent string for all 431 // the RPCs. 432 func WithUserAgent(s string) DialOption { 433 return newFuncDialOption(func(o *dialOptions) { 434 o.copts.UserAgent = s 435 }) 436 } 437 438 // WithKeepaliveParams returns a DialOption that specifies keepalive parameters 439 // for the client transport. 440 func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption { 441 if kp.Time < internal.KeepaliveMinPingTime { 442 logger.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime) 443 kp.Time = internal.KeepaliveMinPingTime 444 } 445 return newFuncDialOption(func(o *dialOptions) { 446 o.copts.KeepaliveParams = kp 447 }) 448 } 449 450 // WithUnaryInterceptor returns a DialOption that specifies the interceptor for 451 // unary RPCs. 452 func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption { 453 return newFuncDialOption(func(o *dialOptions) { 454 o.unaryInt = f 455 }) 456 } 457 458 // WithChainUnaryInterceptor returns a DialOption that specifies the chained 459 // interceptor for unary RPCs. The first interceptor will be the outer most, 460 // while the last interceptor will be the inner most wrapper around the real call. 461 // All interceptors added by this method will be chained, and the interceptor 462 // defined by WithUnaryInterceptor will always be prepended to the chain. 463 func WithChainUnaryInterceptor(interceptors ...UnaryClientInterceptor) DialOption { 464 return newFuncDialOption(func(o *dialOptions) { 465 o.chainUnaryInts = append(o.chainUnaryInts, interceptors...) 466 }) 467 } 468 469 // WithStreamInterceptor returns a DialOption that specifies the interceptor for 470 // streaming RPCs. 471 func WithStreamInterceptor(f StreamClientInterceptor) DialOption { 472 return newFuncDialOption(func(o *dialOptions) { 473 o.streamInt = f 474 }) 475 } 476 477 // WithChainStreamInterceptor returns a DialOption that specifies the chained 478 // interceptor for streaming RPCs. The first interceptor will be the outer most, 479 // while the last interceptor will be the inner most wrapper around the real call. 480 // All interceptors added by this method will be chained, and the interceptor 481 // defined by WithStreamInterceptor will always be prepended to the chain. 482 func WithChainStreamInterceptor(interceptors ...StreamClientInterceptor) DialOption { 483 return newFuncDialOption(func(o *dialOptions) { 484 o.chainStreamInts = append(o.chainStreamInts, interceptors...) 485 }) 486 } 487 488 // WithAuthority returns a DialOption that specifies the value to be used as the 489 // :authority pseudo-header and as the server name in authentication handshake. 490 func WithAuthority(a string) DialOption { 491 return newFuncDialOption(func(o *dialOptions) { 492 o.authority = a 493 }) 494 } 495 496 // WithChannelzParentID returns a DialOption that specifies the channelz ID of 497 // current ClientConn's parent. This function is used in nested channel creation 498 // (e.g. grpclb dial). 499 // 500 // Experimental 501 // 502 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 503 // later release. 504 func WithChannelzParentID(id int64) DialOption { 505 return newFuncDialOption(func(o *dialOptions) { 506 o.channelzParentID = id 507 }) 508 } 509 510 // WithDisableServiceConfig returns a DialOption that causes gRPC to ignore any 511 // service config provided by the resolver and provides a hint to the resolver 512 // to not fetch service configs. 513 // 514 // Note that this dial option only disables service config from resolver. If 515 // default service config is provided, gRPC will use the default service config. 516 func WithDisableServiceConfig() DialOption { 517 return newFuncDialOption(func(o *dialOptions) { 518 o.disableServiceConfig = true 519 }) 520 } 521 522 // WithDefaultServiceConfig returns a DialOption that configures the default 523 // service config, which will be used in cases where: 524 // 525 // 1. WithDisableServiceConfig is also used, or 526 // 527 // 2. The name resolver does not provide a service config or provides an 528 // invalid service config. 529 // 530 // The parameter s is the JSON representation of the default service config. 531 // For more information about service configs, see: 532 // https://github.com/grpc/grpc/blob/master/doc/service_config.md 533 // For a simple example of usage, see: 534 // examples/features/load_balancing/client/main.go 535 func WithDefaultServiceConfig(s string) DialOption { 536 return newFuncDialOption(func(o *dialOptions) { 537 o.defaultServiceConfigRawJSON = &s 538 }) 539 } 540 541 // WithDisableRetry returns a DialOption that disables retries, even if the 542 // service config enables them. This does not impact transparent retries, which 543 // will happen automatically if no data is written to the wire or if the RPC is 544 // unprocessed by the remote server. 545 // 546 // Retry support is currently enabled by default, but may be disabled by 547 // setting the environment variable "GRPC_GO_RETRY" to "off". 548 //goland:noinspection GoUnusedExportedFunction 549 func WithDisableRetry() DialOption { 550 return newFuncDialOption(func(o *dialOptions) { 551 o.disableRetry = true 552 }) 553 } 554 555 // WithMaxHeaderListSize returns a DialOption that specifies the maximum 556 // (uncompressed) size of header list that the client is prepared to accept. 557 func WithMaxHeaderListSize(s uint32) DialOption { 558 return newFuncDialOption(func(o *dialOptions) { 559 o.copts.MaxHeaderListSize = &s 560 }) 561 } 562 563 // WithDisableHealthCheck disables the LB channel health checking for all 564 // SubConns of this ClientConn. 565 // 566 // Experimental 567 // 568 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 569 // later release. 570 func WithDisableHealthCheck() DialOption { 571 return newFuncDialOption(func(o *dialOptions) { 572 o.disableHealthCheck = true 573 }) 574 } 575 576 // withHealthCheckFunc replaces the default health check function with the 577 // provided one. It makes tests easier to change the health check function. 578 // 579 // For testing purpose only. 580 func withHealthCheckFunc(f internal.HealthChecker) DialOption { 581 return newFuncDialOption(func(o *dialOptions) { 582 o.healthCheckFunc = f 583 }) 584 } 585 586 func defaultDialOptions() dialOptions { 587 return dialOptions{ 588 healthCheckFunc: internal.HealthCheckFunc, 589 copts: transport.ConnectOptions{ 590 WriteBufferSize: defaultWriteBufSize, 591 ReadBufferSize: defaultReadBufSize, 592 UseProxy: true, 593 }, 594 } 595 } 596 597 // withGetMinConnectDeadline specifies the function that clientconn uses to 598 // get minConnectDeadline. This can be used to make connection attempts happen 599 // faster/slower. 600 // 601 // For testing purpose only. 602 func withMinConnectDeadline(f func() time.Duration) DialOption { 603 return newFuncDialOption(func(o *dialOptions) { 604 o.minConnectTimeout = f 605 }) 606 } 607 608 // WithResolvers allows a list of resolver implementations to be registered 609 // locally with the ClientConn without needing to be globally registered via 610 // resolver.Register. They will be matched against the scheme used for the 611 // current Dial only, and will take precedence over the global registry. 612 // 613 // Experimental 614 // 615 // Notice: This API is EXPERIMENTAL and may be changed or removed in a 616 // later release. 617 func WithResolvers(rs ...resolver.Builder) DialOption { 618 return newFuncDialOption(func(o *dialOptions) { 619 o.resolvers = append(o.resolvers, rs...) 620 }) 621 }