-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NameResolverRegistry with multiple registrations no longer working as of gRPC 1.60+ #11055
Comments
We were mainly trying to preserve compatibility with Can you explain why you aren't registering in the global registry? Could you also explain why you need the multiple NameResolverProviders since this builder is for only a single target string? (I know of multiple reasons for these answers, but am interested in your situation.) I don't think there's a workaround, other than registering in the global registry. To restore the behavior we'd either need to expose some goo to convert NameResolverRegistry's factory back to a registry, or we'd need to add a Ref: #7133 |
Thanks for the quick response @ejona86! Basically, the use case here is for a library function (thus the need to support multiple possible target URI schemes) exported for use in map-reduce jobs. The code here would be executed in relatively isolated container environments, which are difficult to inject startup/shutdown hooks into for the global registry route (unless I'm misunderstanding how that works - I couldn't find too many examples of custom NameResolvers.) |
Quick reply only partly responding: |
Thanks @ejona86 ! Unfortunately some of our resolvers do need extra config. As a workaround, the best thing I can think of for right now is a targetUri-aware NameResolverProvider, something like: class TargetAwareNameResolverProvider extends NameResolverProvider {
private final String targetScheme;
private final NameResolver nameResolver;
TargetAwareNameResolverProvider(URI targetUri, NameResolver.Args args) {
this.targetScheme = targetUri.getScheme();
switch (this.targetScheme) {
case "s1":
this.nameResolver = Resolver("s1")
break;
// etc
}
}
@Override
public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
// assert targetUri scheme matches expected...
return this.nameResolver;
}
@Override
public String getDefaultScheme() {
return this.targetScheme;
}
} Also - do you think it makes sense to add validation to |
How is the library function you are exposing used? Something like (?): builder = ManagedChannelBuilder.forTarget("foo://");
yourLibrary.configure(builder);
builder.build(); How much of a problem would it be if we solved this by adding a new method
There's no way to check via the Factory API. |
It's pretty opinionated -- it accepts a
So it would directly set |
Is that state stable for the life of the process? And is the config simply data; nothing that needs to be cleaned up/shut down? Where I'm going with this: Could you add the resolvers to the registry on first use of your library function? I'm simultaneously trying to figure out the best workaround and long-term approach. One thing I have been considering is passing NameResolverRegistry when creating the channel builder. The problem with the current |
Yeah! so I could do something like the snippet above, which isn't too much trouble, it just adds an extra layer of URI/scheme parsing on top of what the channel lookup is already doing.
Yes, it's simply data! would you mind expanding a bit on how this would work? i.e. would it be done by the library user? |
This only works if you are just injecting data (yay!) and if the configuration is stable for the life of the process (dunno). Basically, it would probably work if "you always use the same configuration in the registry" today. class YourLibraryClient {
private static final Object lock = new Object();
private static boolean inited;
public YourLibraryClient create(String target, String serviceConfig) {
synchronized (lock) {
if (!inited) {
inited = true;
NameResolverRegistry.getDefault().register(Resolver("s1"));
NameResolverRegistry.getDefault().register(Resolver("s2"));
NameResolverRegistry.getDefault().register(Resolver("s3"));
}
}
// your existing code
} |
API review meeting:
|
As of #10590, the behavior of ManagedChannelImplBuilder#nameResolverFactory has changed -- it now wraps the provided
resolverFactory
into an NameResolverFactoryToProviderFacade that returns the first registered NameResolverProvider's scheme as itsdefaultScheme()
. As a result, lookups of any other registered schemes fail.Here's a code sample of something that used to work pre-1.60.0 (apologies for the Scala code):
After upgrading to GRPC 1.60,
.build()
throws the following exception:Setting an IDE breakpoint in ManagedChannelImpl#getNameResolver shows:
So what's happening is that there's technically no longer a provider for
s2
, because the singular wrapper classNameResolverFactoryToProviderFacade
has a registered scheme ofs1
.Is there anything I can do to work around this? thanks!
The text was updated successfully, but these errors were encountered: