Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 

503 рядки
17 KiB

  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. package grpc
  19. import (
  20. "context"
  21. "fmt"
  22. "net"
  23. "time"
  24. "google.golang.org/grpc/balancer"
  25. "google.golang.org/grpc/credentials"
  26. "google.golang.org/grpc/grpclog"
  27. "google.golang.org/grpc/internal"
  28. "google.golang.org/grpc/internal/backoff"
  29. "google.golang.org/grpc/internal/envconfig"
  30. "google.golang.org/grpc/internal/transport"
  31. "google.golang.org/grpc/keepalive"
  32. "google.golang.org/grpc/resolver"
  33. "google.golang.org/grpc/stats"
  34. )
  35. // dialOptions configure a Dial call. dialOptions are set by the DialOption
  36. // values passed to Dial.
  37. type dialOptions struct {
  38. unaryInt UnaryClientInterceptor
  39. streamInt StreamClientInterceptor
  40. cp Compressor
  41. dc Decompressor
  42. bs backoff.Strategy
  43. block bool
  44. insecure bool
  45. timeout time.Duration
  46. scChan <-chan ServiceConfig
  47. authority string
  48. copts transport.ConnectOptions
  49. callOptions []CallOption
  50. // This is used by v1 balancer dial option WithBalancer to support v1
  51. // balancer, and also by WithBalancerName dial option.
  52. balancerBuilder balancer.Builder
  53. // This is to support grpclb.
  54. resolverBuilder resolver.Builder
  55. reqHandshake envconfig.RequireHandshakeSetting
  56. channelzParentID int64
  57. disableServiceConfig bool
  58. disableRetry bool
  59. disableHealthCheck bool
  60. healthCheckFunc internal.HealthChecker
  61. }
  62. // DialOption configures how we set up the connection.
  63. type DialOption interface {
  64. apply(*dialOptions)
  65. }
  66. // EmptyDialOption does not alter the dial configuration. It can be embedded in
  67. // another structure to build custom dial options.
  68. //
  69. // This API is EXPERIMENTAL.
  70. type EmptyDialOption struct{}
  71. func (EmptyDialOption) apply(*dialOptions) {}
  72. // funcDialOption wraps a function that modifies dialOptions into an
  73. // implementation of the DialOption interface.
  74. type funcDialOption struct {
  75. f func(*dialOptions)
  76. }
  77. func (fdo *funcDialOption) apply(do *dialOptions) {
  78. fdo.f(do)
  79. }
  80. func newFuncDialOption(f func(*dialOptions)) *funcDialOption {
  81. return &funcDialOption{
  82. f: f,
  83. }
  84. }
  85. // WithWaitForHandshake blocks until the initial settings frame is received from
  86. // the server before assigning RPCs to the connection.
  87. //
  88. // Deprecated: this is the default behavior, and this option will be removed
  89. // after the 1.18 release.
  90. func WithWaitForHandshake() DialOption {
  91. return newFuncDialOption(func(o *dialOptions) {
  92. o.reqHandshake = envconfig.RequireHandshakeOn
  93. })
  94. }
  95. // WithWriteBufferSize determines how much data can be batched before doing a
  96. // write on the wire. The corresponding memory allocation for this buffer will
  97. // be twice the size to keep syscalls low. The default value for this buffer is
  98. // 32KB.
  99. //
  100. // Zero will disable the write buffer such that each write will be on underlying
  101. // connection. Note: A Send call may not directly translate to a write.
  102. func WithWriteBufferSize(s int) DialOption {
  103. return newFuncDialOption(func(o *dialOptions) {
  104. o.copts.WriteBufferSize = s
  105. })
  106. }
  107. // WithReadBufferSize lets you set the size of read buffer, this determines how
  108. // much data can be read at most for each read syscall.
  109. //
  110. // The default value for this buffer is 32KB. Zero will disable read buffer for
  111. // a connection so data framer can access the underlying conn directly.
  112. func WithReadBufferSize(s int) DialOption {
  113. return newFuncDialOption(func(o *dialOptions) {
  114. o.copts.ReadBufferSize = s
  115. })
  116. }
  117. // WithInitialWindowSize returns a DialOption which sets the value for initial
  118. // window size on a stream. The lower bound for window size is 64K and any value
  119. // smaller than that will be ignored.
  120. func WithInitialWindowSize(s int32) DialOption {
  121. return newFuncDialOption(func(o *dialOptions) {
  122. o.copts.InitialWindowSize = s
  123. })
  124. }
  125. // WithInitialConnWindowSize returns a DialOption which sets the value for
  126. // initial window size on a connection. The lower bound for window size is 64K
  127. // and any value smaller than that will be ignored.
  128. func WithInitialConnWindowSize(s int32) DialOption {
  129. return newFuncDialOption(func(o *dialOptions) {
  130. o.copts.InitialConnWindowSize = s
  131. })
  132. }
  133. // WithMaxMsgSize returns a DialOption which sets the maximum message size the
  134. // client can receive.
  135. //
  136. // Deprecated: use WithDefaultCallOptions(MaxCallRecvMsgSize(s)) instead.
  137. func WithMaxMsgSize(s int) DialOption {
  138. return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
  139. }
  140. // WithDefaultCallOptions returns a DialOption which sets the default
  141. // CallOptions for calls over the connection.
  142. func WithDefaultCallOptions(cos ...CallOption) DialOption {
  143. return newFuncDialOption(func(o *dialOptions) {
  144. o.callOptions = append(o.callOptions, cos...)
  145. })
  146. }
  147. // WithCodec returns a DialOption which sets a codec for message marshaling and
  148. // unmarshaling.
  149. //
  150. // Deprecated: use WithDefaultCallOptions(ForceCodec(_)) instead.
  151. func WithCodec(c Codec) DialOption {
  152. return WithDefaultCallOptions(CallCustomCodec(c))
  153. }
  154. // WithCompressor returns a DialOption which sets a Compressor to use for
  155. // message compression. It has lower priority than the compressor set by the
  156. // UseCompressor CallOption.
  157. //
  158. // Deprecated: use UseCompressor instead.
  159. func WithCompressor(cp Compressor) DialOption {
  160. return newFuncDialOption(func(o *dialOptions) {
  161. o.cp = cp
  162. })
  163. }
  164. // WithDecompressor returns a DialOption which sets a Decompressor to use for
  165. // incoming message decompression. If incoming response messages are encoded
  166. // using the decompressor's Type(), it will be used. Otherwise, the message
  167. // encoding will be used to look up the compressor registered via
  168. // encoding.RegisterCompressor, which will then be used to decompress the
  169. // message. If no compressor is registered for the encoding, an Unimplemented
  170. // status error will be returned.
  171. //
  172. // Deprecated: use encoding.RegisterCompressor instead.
  173. func WithDecompressor(dc Decompressor) DialOption {
  174. return newFuncDialOption(func(o *dialOptions) {
  175. o.dc = dc
  176. })
  177. }
  178. // WithBalancer returns a DialOption which sets a load balancer with the v1 API.
  179. // Name resolver will be ignored if this DialOption is specified.
  180. //
  181. // Deprecated: use the new balancer APIs in balancer package and
  182. // WithBalancerName.
  183. func WithBalancer(b Balancer) DialOption {
  184. return newFuncDialOption(func(o *dialOptions) {
  185. o.balancerBuilder = &balancerWrapperBuilder{
  186. b: b,
  187. }
  188. })
  189. }
  190. // WithBalancerName sets the balancer that the ClientConn will be initialized
  191. // with. Balancer registered with balancerName will be used. This function
  192. // panics if no balancer was registered by balancerName.
  193. //
  194. // The balancer cannot be overridden by balancer option specified by service
  195. // config.
  196. //
  197. // This is an EXPERIMENTAL API.
  198. func WithBalancerName(balancerName string) DialOption {
  199. builder := balancer.Get(balancerName)
  200. if builder == nil {
  201. panic(fmt.Sprintf("grpc.WithBalancerName: no balancer is registered for name %v", balancerName))
  202. }
  203. return newFuncDialOption(func(o *dialOptions) {
  204. o.balancerBuilder = builder
  205. })
  206. }
  207. // withResolverBuilder is only for grpclb.
  208. func withResolverBuilder(b resolver.Builder) DialOption {
  209. return newFuncDialOption(func(o *dialOptions) {
  210. o.resolverBuilder = b
  211. })
  212. }
  213. // WithServiceConfig returns a DialOption which has a channel to read the
  214. // service configuration.
  215. //
  216. // Deprecated: service config should be received through name resolver, as
  217. // specified here.
  218. // https://github.com/grpc/grpc/blob/master/doc/service_config.md
  219. func WithServiceConfig(c <-chan ServiceConfig) DialOption {
  220. return newFuncDialOption(func(o *dialOptions) {
  221. o.scChan = c
  222. })
  223. }
  224. // WithBackoffMaxDelay configures the dialer to use the provided maximum delay
  225. // when backing off after failed connection attempts.
  226. func WithBackoffMaxDelay(md time.Duration) DialOption {
  227. return WithBackoffConfig(BackoffConfig{MaxDelay: md})
  228. }
  229. // WithBackoffConfig configures the dialer to use the provided backoff
  230. // parameters after connection failures.
  231. //
  232. // Use WithBackoffMaxDelay until more parameters on BackoffConfig are opened up
  233. // for use.
  234. func WithBackoffConfig(b BackoffConfig) DialOption {
  235. return withBackoff(backoff.Exponential{
  236. MaxDelay: b.MaxDelay,
  237. })
  238. }
  239. // withBackoff sets the backoff strategy used for connectRetryNum after a failed
  240. // connection attempt.
  241. //
  242. // This can be exported if arbitrary backoff strategies are allowed by gRPC.
  243. func withBackoff(bs backoff.Strategy) DialOption {
  244. return newFuncDialOption(func(o *dialOptions) {
  245. o.bs = bs
  246. })
  247. }
  248. // WithBlock returns a DialOption which makes caller of Dial blocks until the
  249. // underlying connection is up. Without this, Dial returns immediately and
  250. // connecting the server happens in background.
  251. func WithBlock() DialOption {
  252. return newFuncDialOption(func(o *dialOptions) {
  253. o.block = true
  254. })
  255. }
  256. // WithInsecure returns a DialOption which disables transport security for this
  257. // ClientConn. Note that transport security is required unless WithInsecure is
  258. // set.
  259. func WithInsecure() DialOption {
  260. return newFuncDialOption(func(o *dialOptions) {
  261. o.insecure = true
  262. })
  263. }
  264. // WithTransportCredentials returns a DialOption which configures a connection
  265. // level security credentials (e.g., TLS/SSL). This should not be used together
  266. // with WithCredentialsBundle.
  267. func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
  268. return newFuncDialOption(func(o *dialOptions) {
  269. o.copts.TransportCredentials = creds
  270. })
  271. }
  272. // WithPerRPCCredentials returns a DialOption which sets credentials and places
  273. // auth state on each outbound RPC.
  274. func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
  275. return newFuncDialOption(func(o *dialOptions) {
  276. o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
  277. })
  278. }
  279. // WithCredentialsBundle returns a DialOption to set a credentials bundle for
  280. // the ClientConn.WithCreds. This should not be used together with
  281. // WithTransportCredentials.
  282. //
  283. // This API is experimental.
  284. func WithCredentialsBundle(b credentials.Bundle) DialOption {
  285. return newFuncDialOption(func(o *dialOptions) {
  286. o.copts.CredsBundle = b
  287. })
  288. }
  289. // WithTimeout returns a DialOption that configures a timeout for dialing a
  290. // ClientConn initially. This is valid if and only if WithBlock() is present.
  291. //
  292. // Deprecated: use DialContext and context.WithTimeout instead.
  293. func WithTimeout(d time.Duration) DialOption {
  294. return newFuncDialOption(func(o *dialOptions) {
  295. o.timeout = d
  296. })
  297. }
  298. // WithContextDialer returns a DialOption that sets a dialer to create
  299. // connections. If FailOnNonTempDialError() is set to true, and an error is
  300. // returned by f, gRPC checks the error's Temporary() method to decide if it
  301. // should try to reconnect to the network address.
  302. func WithContextDialer(f func(context.Context, string) (net.Conn, error)) DialOption {
  303. return newFuncDialOption(func(o *dialOptions) {
  304. o.copts.Dialer = f
  305. })
  306. }
  307. func init() {
  308. internal.WithResolverBuilder = withResolverBuilder
  309. internal.WithHealthCheckFunc = withHealthCheckFunc
  310. }
  311. // WithDialer returns a DialOption that specifies a function to use for dialing
  312. // network addresses. If FailOnNonTempDialError() is set to true, and an error
  313. // is returned by f, gRPC checks the error's Temporary() method to decide if it
  314. // should try to reconnect to the network address.
  315. //
  316. // Deprecated: use WithContextDialer instead
  317. func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
  318. return WithContextDialer(
  319. func(ctx context.Context, addr string) (net.Conn, error) {
  320. if deadline, ok := ctx.Deadline(); ok {
  321. return f(addr, time.Until(deadline))
  322. }
  323. return f(addr, 0)
  324. })
  325. }
  326. // WithStatsHandler returns a DialOption that specifies the stats handler for
  327. // all the RPCs and underlying network connections in this ClientConn.
  328. func WithStatsHandler(h stats.Handler) DialOption {
  329. return newFuncDialOption(func(o *dialOptions) {
  330. o.copts.StatsHandler = h
  331. })
  332. }
  333. // FailOnNonTempDialError returns a DialOption that specifies if gRPC fails on
  334. // non-temporary dial errors. If f is true, and dialer returns a non-temporary
  335. // error, gRPC will fail the connection to the network address and won't try to
  336. // reconnect. The default value of FailOnNonTempDialError is false.
  337. //
  338. // FailOnNonTempDialError only affects the initial dial, and does not do
  339. // anything useful unless you are also using WithBlock().
  340. //
  341. // This is an EXPERIMENTAL API.
  342. func FailOnNonTempDialError(f bool) DialOption {
  343. return newFuncDialOption(func(o *dialOptions) {
  344. o.copts.FailOnNonTempDialError = f
  345. })
  346. }
  347. // WithUserAgent returns a DialOption that specifies a user agent string for all
  348. // the RPCs.
  349. func WithUserAgent(s string) DialOption {
  350. return newFuncDialOption(func(o *dialOptions) {
  351. o.copts.UserAgent = s
  352. })
  353. }
  354. // WithKeepaliveParams returns a DialOption that specifies keepalive parameters
  355. // for the client transport.
  356. func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
  357. if kp.Time < internal.KeepaliveMinPingTime {
  358. grpclog.Warningf("Adjusting keepalive ping interval to minimum period of %v", internal.KeepaliveMinPingTime)
  359. kp.Time = internal.KeepaliveMinPingTime
  360. }
  361. return newFuncDialOption(func(o *dialOptions) {
  362. o.copts.KeepaliveParams = kp
  363. })
  364. }
  365. // WithUnaryInterceptor returns a DialOption that specifies the interceptor for
  366. // unary RPCs.
  367. func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
  368. return newFuncDialOption(func(o *dialOptions) {
  369. o.unaryInt = f
  370. })
  371. }
  372. // WithStreamInterceptor returns a DialOption that specifies the interceptor for
  373. // streaming RPCs.
  374. func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
  375. return newFuncDialOption(func(o *dialOptions) {
  376. o.streamInt = f
  377. })
  378. }
  379. // WithAuthority returns a DialOption that specifies the value to be used as the
  380. // :authority pseudo-header. This value only works with WithInsecure and has no
  381. // effect if TransportCredentials are present.
  382. func WithAuthority(a string) DialOption {
  383. return newFuncDialOption(func(o *dialOptions) {
  384. o.authority = a
  385. })
  386. }
  387. // WithChannelzParentID returns a DialOption that specifies the channelz ID of
  388. // current ClientConn's parent. This function is used in nested channel creation
  389. // (e.g. grpclb dial).
  390. func WithChannelzParentID(id int64) DialOption {
  391. return newFuncDialOption(func(o *dialOptions) {
  392. o.channelzParentID = id
  393. })
  394. }
  395. // WithDisableServiceConfig returns a DialOption that causes grpc to ignore any
  396. // service config provided by the resolver and provides a hint to the resolver
  397. // to not fetch service configs.
  398. func WithDisableServiceConfig() DialOption {
  399. return newFuncDialOption(func(o *dialOptions) {
  400. o.disableServiceConfig = true
  401. })
  402. }
  403. // WithDisableRetry returns a DialOption that disables retries, even if the
  404. // service config enables them. This does not impact transparent retries, which
  405. // will happen automatically if no data is written to the wire or if the RPC is
  406. // unprocessed by the remote server.
  407. //
  408. // Retry support is currently disabled by default, but will be enabled by
  409. // default in the future. Until then, it may be enabled by setting the
  410. // environment variable "GRPC_GO_RETRY" to "on".
  411. //
  412. // This API is EXPERIMENTAL.
  413. func WithDisableRetry() DialOption {
  414. return newFuncDialOption(func(o *dialOptions) {
  415. o.disableRetry = true
  416. })
  417. }
  418. // WithMaxHeaderListSize returns a DialOption that specifies the maximum
  419. // (uncompressed) size of header list that the client is prepared to accept.
  420. func WithMaxHeaderListSize(s uint32) DialOption {
  421. return newFuncDialOption(func(o *dialOptions) {
  422. o.copts.MaxHeaderListSize = &s
  423. })
  424. }
  425. // WithDisableHealthCheck disables the LB channel health checking for all SubConns of this ClientConn.
  426. //
  427. // This API is EXPERIMENTAL.
  428. func WithDisableHealthCheck() DialOption {
  429. return newFuncDialOption(func(o *dialOptions) {
  430. o.disableHealthCheck = true
  431. })
  432. }
  433. // withHealthCheckFunc replaces the default health check function with the provided one. It makes
  434. // tests easier to change the health check function.
  435. //
  436. // For testing purpose only.
  437. func withHealthCheckFunc(f internal.HealthChecker) DialOption {
  438. return newFuncDialOption(func(o *dialOptions) {
  439. o.healthCheckFunc = f
  440. })
  441. }
  442. func defaultDialOptions() dialOptions {
  443. return dialOptions{
  444. disableRetry: !envconfig.Retry,
  445. reqHandshake: envconfig.RequireHandshake,
  446. healthCheckFunc: internal.HealthCheckFunc,
  447. copts: transport.ConnectOptions{
  448. WriteBufferSize: defaultWriteBufSize,
  449. ReadBufferSize: defaultReadBufSize,
  450. },
  451. }
  452. }