go.uber.org/yarpc@v1.72.1/transport/tchannel/options.go (about) 1 // Copyright (c) 2022 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package tchannel 22 23 import ( 24 "context" 25 "crypto/tls" 26 "net" 27 "time" 28 29 "github.com/opentracing/opentracing-go" 30 "github.com/uber/tchannel-go" 31 "go.uber.org/net/metrics" 32 backoffapi "go.uber.org/yarpc/api/backoff" 33 yarpctls "go.uber.org/yarpc/api/transport/tls" 34 "go.uber.org/yarpc/internal/backoff" 35 "go.uber.org/zap" 36 ) 37 38 // Option allows customizing the YARPC TChannel transport. 39 // TransportSpec() accepts any TransportOption, and may in the future also 40 // accept inbound and outbound options. 41 type Option interface { 42 tchannelOption() 43 } 44 45 var _ Option = (TransportOption)(nil) 46 47 // transportOptions is suitable for conveying options to TChannel transport 48 // constructors (NewTransport and NewChannelTransport). 49 // At time of writing, there is only a ChannelTransport constructor, which 50 // supports options like WithChannel that only apply to this constructor form. 51 // The transportOptions should also be suitable, albeit with extraneous properties, 52 // if used for NewTransport, which will return a Transport suitable for YARPC 53 // peer lists. 54 // TODO update above when NewTransport is real. 55 type transportOptions struct { 56 ch Channel 57 tracer opentracing.Tracer 58 logger *zap.Logger 59 meter *metrics.Scope 60 addr string 61 listener net.Listener 62 dialer func(ctx context.Context, network, hostPort string) (net.Conn, error) 63 name string 64 connTimeout time.Duration 65 connBackoffStrategy backoffapi.Strategy 66 originalHeaders bool 67 nativeTChannelMethods NativeTChannelMethods 68 excludeServiceHeaderInResponse bool 69 inboundTLSConfig *tls.Config 70 inboundTLSMode *yarpctls.Mode 71 outboundTLSConfigProvider yarpctls.OutboundTLSConfigProvider 72 } 73 74 // newTransportOptions constructs the default transport options struct 75 func newTransportOptions() transportOptions { 76 return transportOptions{ 77 tracer: opentracing.GlobalTracer(), 78 connTimeout: defaultConnTimeout, 79 connBackoffStrategy: backoff.DefaultExponential, 80 } 81 } 82 83 // TransportOption customizes the behavior of a TChannel Transport. 84 type TransportOption func(*transportOptions) 85 86 // TransportOption makes all TransportOptions recognizeable as Option so 87 // TransportSpec will accept them. 88 func (TransportOption) tchannelOption() {} 89 90 // Tracer specifies the request tracer used for RPCs passing through the 91 // TChannel transport. 92 func Tracer(tracer opentracing.Tracer) TransportOption { 93 return func(t *transportOptions) { 94 t.tracer = tracer 95 } 96 } 97 98 // Logger sets a logger to use for internal logging. 99 // 100 // The default is to not write any logs. 101 func Logger(logger *zap.Logger) TransportOption { 102 return func(t *transportOptions) { 103 t.logger = logger 104 } 105 } 106 107 // Meter sets a meter to use for transport metrics. 108 // 109 // The default is to not emit any transport metrics. 110 func Meter(meter *metrics.Scope) TransportOption { 111 return func(t *transportOptions) { 112 t.meter = meter 113 } 114 } 115 116 // OutboundTLSConfigProvider returns a TransportOption that provides the 117 // outbound TLS config provider. 118 func OutboundTLSConfigProvider(provider yarpctls.OutboundTLSConfigProvider) TransportOption { 119 return func(transportOptions *transportOptions) { 120 transportOptions.outboundTLSConfigProvider = provider 121 } 122 } 123 124 // WithChannel specifies the TChannel Channel to use to send and receive YARPC 125 // requests. The instance may already have handlers registered against it; 126 // these will be left unchanged. 127 // 128 // If this option is not passed, the Transport will build and manage its own 129 // Channel. The behavior of that TChannel may be customized using the 130 // ListenAddr and ServiceName options. 131 // 132 // This option is disallowed for NewTransport and transports constructed with 133 // the YARPC configuration system. 134 func WithChannel(ch Channel) TransportOption { 135 return func(options *transportOptions) { 136 options.ch = ch 137 } 138 } 139 140 // ListenAddr specifies the port the TChannel should listen on. This defaults 141 // to ":0" (all interfaces, OS-assigned port). 142 // 143 // transport := NewChannelTransport(ServiceName("myservice"), ListenAddr(":4040")) 144 // 145 // This option has no effect if WithChannel was used and the TChannel was 146 // already listening, and it is disallowed for transports constructed with the 147 // YARPC configuration system. 148 func ListenAddr(addr string) TransportOption { 149 return func(options *transportOptions) { 150 options.addr = addr 151 } 152 } 153 154 // Listener sets a net.Listener to use for the channel. This only applies to 155 // NewTransport (will not work with NewChannelTransport). 156 // 157 // The default is to depend on the ListenAddr (no-op). 158 func Listener(l net.Listener) TransportOption { 159 return func(t *transportOptions) { 160 t.listener = l 161 } 162 } 163 164 // Dialer sets a dialer function for outbound calls. 165 // 166 // The function signature matches the net.Dialer DialContext method. 167 // https://golang.org/pkg/net/#Dialer.DialContext 168 func Dialer(dialer func(ctx context.Context, network, hostPort string) (net.Conn, error)) TransportOption { 169 return func(t *transportOptions) { 170 t.dialer = dialer 171 } 172 } 173 174 // ServiceName informs the NewChannelTransport constructor which service 175 // name to use if it needs to construct a root Channel object, as when called 176 // without the WithChannel option. 177 // 178 // ServiceName specifies the name of the current service for the YARPC-owned 179 // TChannel Channel. If the WithChannel option is not specified, the TChannel 180 // Transport will build its own TChannel Chanel and use this name for that 181 // Channel. 182 // 183 // This option has no effect if WithChannel was used, and it is disallowed for 184 // transports constructed with the YARPC configuration system. 185 func ServiceName(name string) TransportOption { 186 return func(options *transportOptions) { 187 options.name = name 188 } 189 } 190 191 // ConnTimeout specifies the time that TChannel will wait for a 192 // connection attempt to any retained peer. 193 // 194 // The default is half of a second. 195 func ConnTimeout(d time.Duration) TransportOption { 196 return func(options *transportOptions) { 197 options.connTimeout = d 198 } 199 } 200 201 // ConnBackoff specifies the connection backoff strategy for delays between 202 // connection attempts for each peer. 203 // 204 // ConnBackoff accepts a function that creates new backoff instances. 205 // The transport uses this to make referentially independent backoff instances 206 // that will not be shared across goroutines. 207 // 208 // The backoff instance is a function that accepts connection attempts and 209 // returns a duration. 210 // 211 // The default is exponential backoff starting with 10ms fully jittered, 212 // doubling each attempt, with a maximum interval of 30s. 213 func ConnBackoff(s backoffapi.Strategy) TransportOption { 214 return func(options *transportOptions) { 215 options.connBackoffStrategy = s 216 } 217 } 218 219 // OriginalHeaders specifies whether to forward headers without canonicalizing them 220 func OriginalHeaders() TransportOption { 221 return func(options *transportOptions) { 222 options.originalHeaders = true 223 } 224 } 225 226 // NativeTChannelMethods interface exposes methods which returns all 227 // the native TChannel methods and list of method names whose requests must 228 // be handled by the provided TChannel handlers. 229 type NativeTChannelMethods interface { 230 // Methods returns a map of all the native handlers by method name. 231 Methods() map[string]tchannel.Handler 232 233 // SkipMethodNames returns a list of method names whose requests must be 234 // handled by the provide TChannel handlers. 235 SkipMethodNames() []string 236 } 237 238 // WithNativeTChannelMethods specifies the list of methods whose requests must 239 // be handled by the provided native TChannel method handlers. 240 // 241 // Requests with other methods will be handled by the Yarpc router. 242 // This is useful for gradual migration. 243 func WithNativeTChannelMethods(nativeMethods NativeTChannelMethods) TransportOption { 244 return func(option *transportOptions) { 245 option.nativeTChannelMethods = nativeMethods 246 } 247 } 248 249 // ExcludeServiceHeaderInResponse stop adding the $rpc$-service response header for inbounds 250 func ExcludeServiceHeaderInResponse() TransportOption { 251 return func(option *transportOptions) { 252 option.excludeServiceHeaderInResponse = true 253 } 254 } 255 256 // InboundTLSMode return TransportOption that sets inbound TLS mode. 257 // It must be noted that TLS configuration must be passed separately using 258 // option InboundTLSConfiguration. 259 func InboundTLSMode(mode yarpctls.Mode) TransportOption { 260 return func(option *transportOptions) { 261 option.inboundTLSMode = &mode 262 } 263 } 264 265 // InboundTLSConfiguration returns TransportOption that provides the TLS 266 // configuration used for setting up TLS inbound. 267 func InboundTLSConfiguration(tlsConfig *tls.Config) TransportOption { 268 return func(option *transportOptions) { 269 option.inboundTLSConfig = tlsConfig 270 } 271 }