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