Skip to content

Commit

Permalink
feat: add support for a lazy refresh (#2184)
Browse files Browse the repository at this point in the history
When clients run the Proxy in environments where the CPU may be
throttled, the background connection info refresh operation can fail to
complete, causing connection errors. This commit introduces an option
for a lazy refresh. Connection info is retrieved on an as needed-basis
and cached based on the associated certificate's expiration. No
background goroutine runs, unlike the default refresh ahead cache.

 Enable it like so:

 ./cloud-sql-proxy <INSTANCE_CONNECTION_NAME> --lazy-refresh

A lazy refresh may result in increased latency (more requests will be
subject to waiting for the refresh to complete), but gains in
reliability.

Fixes #2183
  • Loading branch information
enocom authored Apr 16, 2024
1 parent fdcca22 commit fd7ab82
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 55 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,13 @@ debug-logs = true

Run `./cloud-sql-proxy --help` for more details.

### Configuring a Lazy Refresh

The `--lazy-refresh` flag configures the Proxy to retrieve connection info
lazily and as-needed. Otherwise, no background refresh cycle runs. This setting
is useful in environments where the CPU may be throttled outside of a request
context, e.g., Cloud Run, Cloud Functions, etc.

### Additional flags

To see a full list of flags, use:
Expand Down
8 changes: 8 additions & 0 deletions cmd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,11 @@ func WithDebugLogging() Option {
c.conf.DebugLogs = true
}
}

// WithLazyRefresh configures the Proxy to refresh connection info on an
// as-needed basis when the cached copy has expired.
func WithLazyRefresh() Option {
return func(c *Command) {
c.conf.LazyRefresh = true
}
}
12 changes: 12 additions & 0 deletions cmd/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,18 @@ func TestCommandOptions(t *testing.T) {
},
option: WithQuietLogging(),
},
{
desc: "with lazy refresh",
isValid: func(c *Command) error {
if !c.conf.LazyRefresh {
return errors.New(
"LazyRefresh was false, but should be true",
)
}
return nil
},
option: WithLazyRefresh(),
},
}

for _, tc := range tcs {
Expand Down
6 changes: 6 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,12 @@ is the target account.`)
`Supports legacy behavior of v1 and will try to connect to first IP
address returned by the SQL Admin API. In most cases, this flag should not be used.
Prefer default of public IP or use --private-ip instead.`)
localFlags.BoolVar(&c.conf.LazyRefresh, "lazy-refresh", false,
`Configure a lazy refresh where connection info is retrieved only if
the cached copy has expired. Use this setting in environments where the
CPU may be throttled and a background refresh cannot run reliably
(e.g., Cloud Run)`,
)

localFlags.BoolVar(&c.conf.RunConnectionTest, "run-connection-test", false, `Runs a connection test
against all specified instances. If an instance is unreachable, the Proxy exits with a failure
Expand Down
7 changes: 7 additions & 0 deletions cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,13 @@ func TestNewCommandArguments(t *testing.T) {
Debug: true,
}),
},
{
desc: "using the lazy refresh flag",
args: []string{"--lazy-refresh", "proj:region:inst"},
want: withDefaults(&proxy.Config{
LazyRefresh: true,
}),
},
{
desc: "using the admin port flag",
args: []string{"--admin-port", "7777", "proj:region:inst"},
Expand Down
31 changes: 15 additions & 16 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ module github.com/GoogleCloudPlatform/cloud-sql-proxy/v2
go 1.22

require (
cloud.google.com/go/cloudsqlconn v1.8.1
cloud.google.com/go/cloudsqlconn v1.9.0
contrib.go.opencensus.io/exporter/prometheus v0.4.2
contrib.go.opencensus.io/exporter/stackdriver v0.13.14
github.com/coreos/go-systemd/v22 v22.5.0
github.com/go-sql-driver/mysql v1.8.0
github.com/go-sql-driver/mysql v1.8.1
github.com/google/go-cmp v0.6.0
github.com/hanwen/go-fuse/v2 v2.5.0
github.com/jackc/pgx/v5 v5.5.5
Expand All @@ -17,16 +17,16 @@ require (
github.com/spf13/viper v1.18.2
go.opencensus.io v0.24.0
go.uber.org/zap v1.27.0
golang.org/x/oauth2 v0.18.0
golang.org/x/sys v0.18.0
google.golang.org/api v0.170.0
golang.org/x/oauth2 v0.19.0
golang.org/x/sys v0.19.0
google.golang.org/api v0.172.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
)

require (
cloud.google.com/go/compute v1.23.4 // indirect
cloud.google.com/go/compute v1.24.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/monitoring v1.17.1 // indirect
cloud.google.com/go/monitoring v1.18.0 // indirect
cloud.google.com/go/trace v1.10.5 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/aws/aws-sdk-go v1.43.31 // indirect
Expand All @@ -42,11 +42,11 @@ require (
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
Expand Down Expand Up @@ -75,17 +75,16 @@ require (
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240205150955-31a09d347014 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240311173647-c811ad7063a7 // indirect
google.golang.org/grpc v1.62.1 // indirect
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be // indirect
google.golang.org/grpc v1.63.2 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
Loading

0 comments on commit fd7ab82

Please sign in to comment.