Allow gzip compression to be disabled from rest.Config

Golang automatically enables transport level gzip, but local network
clients may wish to disable it for better CPU usage and lower latency
(scheduler, controller-manager). Allow DisableCompression on rest.Config
to modify the underlying transport. This impacts the transport cache,
but it is expected that most clients connecting to the same servers
within a process will have the same compression config.

Kubernetes-commit: dee6de70d0e4ad381bd5de01b6d1fbd4fde004bc
This commit is contained in:
Clayton Coleman 2019-08-02 14:23:33 -04:00 committed by Kubernetes Publisher
parent fdb3fbe99e
commit 40d852a94d
5 changed files with 47 additions and 33 deletions

View File

@ -94,6 +94,10 @@ type Config struct {
// UserAgent is an optional field that specifies the caller of this request. // UserAgent is an optional field that specifies the caller of this request.
UserAgent string UserAgent string
// DisableCompression bypasses automatic GZip compression requests to the
// server.
DisableCompression bool
// Transport may be used for custom HTTP behavior. This attribute may not // Transport may be used for custom HTTP behavior. This attribute may not
// be specified with the TLS client certificate options. Use WrapTransport // be specified with the TLS client certificate options. Use WrapTransport
// to provide additional per-server middleware behavior. // to provide additional per-server middleware behavior.
@ -500,12 +504,13 @@ func AnonymousClientConfig(config *Config) *Config {
CAFile: config.TLSClientConfig.CAFile, CAFile: config.TLSClientConfig.CAFile,
CAData: config.TLSClientConfig.CAData, CAData: config.TLSClientConfig.CAData,
}, },
RateLimiter: config.RateLimiter, RateLimiter: config.RateLimiter,
UserAgent: config.UserAgent, UserAgent: config.UserAgent,
QPS: config.QPS, DisableCompression: config.DisableCompression,
Burst: config.Burst, QPS: config.QPS,
Timeout: config.Timeout, Burst: config.Burst,
Dial: config.Dial, Timeout: config.Timeout,
Dial: config.Dial,
} }
} }
@ -537,13 +542,14 @@ func CopyConfig(config *Config) *Config {
KeyData: config.TLSClientConfig.KeyData, KeyData: config.TLSClientConfig.KeyData,
CAData: config.TLSClientConfig.CAData, CAData: config.TLSClientConfig.CAData,
}, },
UserAgent: config.UserAgent, UserAgent: config.UserAgent,
Transport: config.Transport, DisableCompression: config.DisableCompression,
WrapTransport: config.WrapTransport, Transport: config.Transport,
QPS: config.QPS, WrapTransport: config.WrapTransport,
Burst: config.Burst, QPS: config.QPS,
RateLimiter: config.RateLimiter, Burst: config.Burst,
Timeout: config.Timeout, RateLimiter: config.RateLimiter,
Dial: config.Dial, Timeout: config.Timeout,
Dial: config.Dial,
} }
} }

View File

@ -508,7 +508,7 @@ func TestConfigSprint(t *testing.T) {
Dial: fakeDialFunc, Dial: fakeDialFunc,
} }
want := fmt.Sprintf( want := fmt.Sprintf(
`&rest.Config{Host:"localhost:8080", APIPath:"v1", ContentConfig:rest.ContentConfig{AcceptContentTypes:"application/json", ContentType:"application/json", GroupVersion:(*schema.GroupVersion)(nil), NegotiatedSerializer:runtime.NegotiatedSerializer(nil)}, Username:"gopher", Password:"--- REDACTED ---", BearerToken:"--- REDACTED ---", BearerTokenFile:"", Impersonate:rest.ImpersonationConfig{UserName:"gopher2", Groups:[]string(nil), Extra:map[string][]string(nil)}, AuthProvider:api.AuthProviderConfig{Name: "gopher", Config: map[string]string{--- REDACTED ---}}, AuthConfigPersister:rest.AuthProviderConfigPersister(--- REDACTED ---), ExecProvider:api.AuthProviderConfig{Command: "sudo", Args: []string{"--- REDACTED ---"}, Env: []ExecEnvVar{--- REDACTED ---}, APIVersion: ""}, TLSClientConfig:rest.sanitizedTLSClientConfig{Insecure:false, ServerName:"", CertFile:"a.crt", KeyFile:"a.key", CAFile:"", CertData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x41, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, KeyData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x52, 0x45, 0x44, 0x41, 0x43, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, CAData:[]uint8(nil)}, UserAgent:"gobot", Transport:(*rest.fakeRoundTripper)(%p), WrapTransport:(transport.WrapperFunc)(%p), QPS:1, Burst:2, RateLimiter:(*rest.fakeLimiter)(%p), Timeout:3000000000, Dial:(func(context.Context, string, string) (net.Conn, error))(%p)}`, `&rest.Config{Host:"localhost:8080", APIPath:"v1", ContentConfig:rest.ContentConfig{AcceptContentTypes:"application/json", ContentType:"application/json", GroupVersion:(*schema.GroupVersion)(nil), NegotiatedSerializer:runtime.NegotiatedSerializer(nil)}, Username:"gopher", Password:"--- REDACTED ---", BearerToken:"--- REDACTED ---", BearerTokenFile:"", Impersonate:rest.ImpersonationConfig{UserName:"gopher2", Groups:[]string(nil), Extra:map[string][]string(nil)}, AuthProvider:api.AuthProviderConfig{Name: "gopher", Config: map[string]string{--- REDACTED ---}}, AuthConfigPersister:rest.AuthProviderConfigPersister(--- REDACTED ---), ExecProvider:api.AuthProviderConfig{Command: "sudo", Args: []string{"--- REDACTED ---"}, Env: []ExecEnvVar{--- REDACTED ---}, APIVersion: ""}, TLSClientConfig:rest.sanitizedTLSClientConfig{Insecure:false, ServerName:"", CertFile:"a.crt", KeyFile:"a.key", CAFile:"", CertData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x54, 0x52, 0x55, 0x4e, 0x43, 0x41, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, KeyData:[]uint8{0x2d, 0x2d, 0x2d, 0x20, 0x52, 0x45, 0x44, 0x41, 0x43, 0x54, 0x45, 0x44, 0x20, 0x2d, 0x2d, 0x2d}, CAData:[]uint8(nil)}, UserAgent:"gobot", DisableCompression:false, Transport:(*rest.fakeRoundTripper)(%p), WrapTransport:(transport.WrapperFunc)(%p), QPS:1, Burst:2, RateLimiter:(*rest.fakeLimiter)(%p), Timeout:3000000000, Dial:(func(context.Context, string, string) (net.Conn, error))(%p)}`,
c.Transport, fakeWrapperFunc, c.RateLimiter, fakeDialFunc, c.Transport, fakeWrapperFunc, c.RateLimiter, fakeDialFunc,
) )

View File

@ -61,9 +61,10 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip
// TransportConfig converts a client config to an appropriate transport config. // TransportConfig converts a client config to an appropriate transport config.
func (c *Config) TransportConfig() (*transport.Config, error) { func (c *Config) TransportConfig() (*transport.Config, error) {
conf := &transport.Config{ conf := &transport.Config{
UserAgent: c.UserAgent, UserAgent: c.UserAgent,
Transport: c.Transport, Transport: c.Transport,
WrapTransport: c.WrapTransport, WrapTransport: c.WrapTransport,
DisableCompression: c.DisableCompression,
TLS: transport.TLSConfig{ TLS: transport.TLSConfig{
Insecure: c.Insecure, Insecure: c.Insecure,
ServerName: c.ServerName, ServerName: c.ServerName,

View File

@ -39,13 +39,14 @@ const idleConnsPerHost = 25
var tlsCache = &tlsTransportCache{transports: make(map[tlsCacheKey]*http.Transport)} var tlsCache = &tlsTransportCache{transports: make(map[tlsCacheKey]*http.Transport)}
type tlsCacheKey struct { type tlsCacheKey struct {
insecure bool insecure bool
caData string caData string
certData string certData string
keyData string keyData string
getCert string getCert string
serverName string serverName string
dial string dial string
disableCompression bool
} }
func (t tlsCacheKey) String() string { func (t tlsCacheKey) String() string {
@ -53,7 +54,7 @@ func (t tlsCacheKey) String() string {
if len(t.keyData) > 0 { if len(t.keyData) > 0 {
keyText = "<redacted>" keyText = "<redacted>"
} }
return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, getCert: %s, serverName:%s, dial:%s", t.insecure, t.caData, t.certData, keyText, t.getCert, t.serverName, t.dial) return fmt.Sprintf("insecure:%v, caData:%#v, certData:%#v, keyData:%s, getCert: %s, serverName:%s, dial:%s disableCompression:%t", t.insecure, t.caData, t.certData, keyText, t.getCert, t.serverName, t.dial, t.disableCompression)
} }
func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) { func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
@ -95,6 +96,7 @@ func (c *tlsTransportCache) get(config *Config) (http.RoundTripper, error) {
TLSClientConfig: tlsConfig, TLSClientConfig: tlsConfig,
MaxIdleConnsPerHost: idleConnsPerHost, MaxIdleConnsPerHost: idleConnsPerHost,
DialContext: dial, DialContext: dial,
DisableCompression: config.DisableCompression,
}) })
return c.transports[key], nil return c.transports[key], nil
} }
@ -106,12 +108,13 @@ func tlsConfigKey(c *Config) (tlsCacheKey, error) {
return tlsCacheKey{}, err return tlsCacheKey{}, err
} }
return tlsCacheKey{ return tlsCacheKey{
insecure: c.TLS.Insecure, insecure: c.TLS.Insecure,
caData: string(c.TLS.CAData), caData: string(c.TLS.CAData),
certData: string(c.TLS.CertData), certData: string(c.TLS.CertData),
keyData: string(c.TLS.KeyData), keyData: string(c.TLS.KeyData),
getCert: fmt.Sprintf("%p", c.TLS.GetCert), getCert: fmt.Sprintf("%p", c.TLS.GetCert),
serverName: c.TLS.ServerName, serverName: c.TLS.ServerName,
dial: fmt.Sprintf("%p", c.Dial), dial: fmt.Sprintf("%p", c.Dial),
disableCompression: c.DisableCompression,
}, nil }, nil
} }

View File

@ -47,6 +47,10 @@ type Config struct {
// Impersonate is the config that this Config will impersonate using // Impersonate is the config that this Config will impersonate using
Impersonate ImpersonationConfig Impersonate ImpersonationConfig
// DisableCompression bypasses automatic GZip compression requests to the
// server.
DisableCompression bool
// Transport may be used for custom HTTP behavior. This attribute may // Transport may be used for custom HTTP behavior. This attribute may
// not be specified with the TLS client certificate options. Use // not be specified with the TLS client certificate options. Use
// WrapTransport for most client level operations. // WrapTransport for most client level operations.