feat(spanner): support MultiEndpoint#9565
Conversation
|
please updated your title to be in the form of |
| option.WithoutAuthentication(), | ||
| internaloption.SkipDialSettingsValidation(), | ||
| } | ||
| opts = append(opts, emulatorOpts...) |
There was a problem hiding this comment.
Note that mutating a var args parameter (opts) is dangerous. This code should be making a copy first.
https://go.dev/play/p/UAEsaz4xxXg
This is a contrived example to illustrate what's happening, but there is real risk in mutating a variadic argument, especially for exported APIs.
| copts := opts | ||
|
|
||
| for _, do := range dopts { | ||
| copts = append(copts, option.WithGRPCDialOption(do)) | ||
| } |
There was a problem hiding this comment.
This could potentially be even worse. If the DialFunc is run concurrently in the ChannelPool, then this function will be overwriting memory in one goroutine while reading it in another, which could cause serious problems, and should be expected to trigger the race detector if nothing else. It looks like that doesn't happen today - grpc clients are created serially, but I could see a user complaining about startup performance and sending a pr that does them each in their own goroutine, and then this becomes broken as a result. A copy should ideally be made before mutating the opts slice.
There was a problem hiding this comment.
Oops, that wasn't intended. Thank you for pointing this out. Sending PR #11151 to fix this.
This PR adds optional gRPC-GCP channel pool (which is available in Cloud Spanner Java client) with its new MultiEndpoint feature.
The MultiEndpoint accepts a grouped lists of endpoints and creates a gRPC-GCP channel pool for each unique endpoint. The purposes of MultiEndpoint are:
endpoint is completely unavailable.
Here is an example of creating a client with MultiEndpoint
Endpoints reconfiguration
Then, with the above example, to route the calls to a different endpoint we can:
And all the following calls in the
clientwill go to the west2 endpoint instead of east4.Using several MultiEndpoints
We can configure several MultiEndpoints, for example:
Then we can route a call to a specific MultiEndpoint ("default" is used by default) using context:
The call above will use an endpoint from the "west" MultiEndpoint group.
Fallback
If we add more than one endpoint to a MultiEndpoint, like in the example below:
Each MultiEndpoint will use the first endpoint in the list as long as any connection to that endpoint is alive.
When all connections to the first endpoint are broken, the MultiEndpoint will wait for
recoveryTimeoutand if the connections are still down, fail over to the next endpoint and so forth.When a connection to one of the previous endpoints in the list is recovered, the MultiEndpoint will switch back to that endpoint after
switchingDelay.