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