Closed
Conversation
chingor13
pushed a commit
that referenced
this pull request
Mar 24, 2026
This PR enables the gRPC-GCP channel pool extension by default for Cloud Spanner Java client.
**What's Changing for Customers**
**Before this change**
- gRPC-GCP extension was disabled by default
- Default number of channels: 4
- Channel pooling was handled by GAX
**After this change**
- gRPC-GCP extension is enabled by default
- Default number of channels: 8
- Channel pooling is handled by gRPC-GCP extension
**Benefits of gRPC-GCP**
- **Improved resilience:** When a network connection fails on a particular channel, operations can be automatically retried on a different gRPC channel
- **Better channel management:** gRPC-GCP provides more sophisticated channel affinity and load balancing
**How to Disable gRPC-GCP (Switch Back to GAX Channel Pool)**
If you need to disable gRPC-GCP and use the previous GAX channel pooling behavior, use the `disableGrpcGcpExtension()` method:
```
SpannerOptions options = SpannerOptions.newBuilder()
.setProjectId("my-project")
.disableGrpcGcpExtension()
.build();
```
When disabled, the default number of channels reverts to 4 (the previous default).
**When You Might Want to Disable gRPC-GCP**
- **Maintaining previous behavior:** If you want to keep the exact same behavior as before this change (GAX channel pool with 4 default channels).
- **Troubleshooting**: If you experience any unexpected behavior, disabling gRPC-GCP can help isolate whether the issue is related to the channel pooling mechanism.
akash329d
added a commit
to akash329d/google-cloud-java
that referenced
this pull request
Apr 9, 2026
The static-pool path bounded the affinity key to (-numChannels..numChannels) distinct values. Under a high-concurrency cold start, all keys race through GcpManagedChannel.pickLeastBusyChannel before any caller's start() has incremented activeStreamsCount, so they all tie to channelRefs[0] and bind there permanently. The result is most RPCs route through a single HTTP/2 connection and queue at MAX_CONCURRENT_STREAMS (~100), capping per-client throughput. Regression became default-path behavior in 6.105.0 (googleapis#4239). With multiplexed sessions there is no per-transaction locality benefit from sticky channel affinity. Dropping the key for the static-pool case makes GcpManagedChannel.getChannelRef(null) do a fresh per-call least-busy pick with no sticky bind, which self-corrects and matches the dynamic-pool / disableGrpcGcpExtension() throughput curve.
akash329d
added a commit
to akash329d/google-cloud-java
that referenced
this pull request
Apr 9, 2026
Under grpc-gcp (default since 6.105.0, googleapis#4239), newCallContext set GcpManagedChannel.AFFINITY_KEY on every data RPC. GcpManagedChannel binds each new key via pickLeastBusyChannel, which reads activeStreamsCount before any concurrent caller's start() has incremented it (tiebreak channelRefs[0]). A high-concurrency cold start therefore binds keys to channel 0 and the bindings are sticky, so RPCs funnel through one HTTP/2 connection and queue at MAX_CONCURRENT_STREAMS. The static-numChannels path bounded the key to ~2*numChannels-1 distinct values, making the collapse permanent (~6x throughput regression at 400 concurrent). The dynamic-channel-pool path used per-transaction random keys and largely self-corrected, but a few BitSet-recycled hints still sticky-bound, leaving a p99 tail. Multiplexed sessions get no backend-locality benefit from sticky per-transaction channel affinity, so don't set the key under grpc-gcp at all. getChannelRef(null) does a fresh per-call least-busy pick with no sticky binding and no affinity-map growth. Drops the now-unobservable distinct-AFFINITY_KEY assertions from RetryOnDifferentGrpcChannelMockServerTest; the request-count and session assertions still cover the retry loop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was generated using Autosynth. 🌈
Here's the log from Synthtool: