in grpc-gcp/src/main/java/com/google/cloud/grpc/GcpManagedChannel.java [1097:1151]
protected ChannelRef getChannelRef(@Nullable String key) {
if (key == null || key.isEmpty()) {
return pickLeastBusyChannel(/* forFallback= */ false);
}
ChannelRef mappedChannel = affinityKeyToChannelRef.get(key);
affinityKeyLastUsed.put(key, System.nanoTime());
if (mappedChannel == null) {
ChannelRef channelRef = pickLeastBusyChannel(/*forFallback= */ false);
bind(channelRef, Collections.singletonList(key));
return channelRef;
}
if (!fallbackEnabled) {
return mappedChannel;
}
// Look up if the channelRef is not ready.
Map<String, Integer> tempMap = fallbackMap.get(mappedChannel.getId());
if (tempMap == null) {
// Channel is ready.
return mappedChannel;
}
// Channel is not ready. Look up if the affinity key mapped to another channel.
Integer channelId = tempMap.get(key);
if (channelId != null && !fallbackMap.containsKey(channelId)) {
// Fallback channel is ready.
if (logger.isLoggable(Level.FINEST)) {
logger.finest(log("Using fallback channel: %d -> %d", mappedChannel.getId(), channelId));
}
fallbacksSucceeded.incrementAndGet();
return channelRefs.get(channelId);
}
// No temp mapping for this key or fallback channel is also broken.
ChannelRef channelRef = pickLeastBusyChannel(/* forFallback= */ true);
if (!fallbackMap.containsKey(channelRef.getId())
&& channelRef.getActiveStreamsCount() < DEFAULT_MAX_STREAM) {
// Got a ready and not an overloaded channel.
if (channelRef.getId() != mappedChannel.getId()) {
if (logger.isLoggable(Level.FINEST)) {
logger.finest(
log("Setting fallback channel: %d -> %d", mappedChannel.getId(), channelRef.getId()));
}
fallbacksSucceeded.incrementAndGet();
tempMap.put(key, channelRef.getId());
}
return channelRef;
}
if (logger.isLoggable(Level.FINEST)) {
logger.finest(log("Failed to find fallback for channel %d", mappedChannel.getId()));
}
fallbacksFailed.incrementAndGet();
if (channelId != null) {
// Stick with previous mapping if fallback has failed.
return channelRefs.get(channelId);
}
return mappedChannel;
}