# gRPC Custom Name Resolver Proposal ## Details | | | |------------------------|------------------------------------| | **Feature Name** | gRPC custom name resolver | | **Type** | enhancement | | **Related components** | gRPC source resolution | ## Summary gRPC by default supports DNS resolution which is currently being used e.g. "localhost:8013" in both [core](https://github.com/open-feature/flagd/blob/main/core/pkg/sync/grpc/grpc_sync.go#L72-L74) and providers e.g. [java](https://github.com/open-feature/java-sdk-contrib/blob/main/providers/flagd/src/main/java/dev/openfeature/contrib/providers/flagd/resolver/common/ChannelBuilder.java#L53-L55). This covers most deployments, but with increased adoption of microservice-architecture, service discovery, policy-enabled service meshes (e.g. istio, envoy, consul, etc) it's necessary to support custom routing and name resolution. For such cases the gRPC core libraries support few alternative resolver* also expose the required interfaces to build custom implementations: ### Reference * [Custom Name Resolution](https://grpc.io/docs/guides/custom-name-resolution/) * [Java Client](https://grpc.github.io/grpc-java/javadoc/io/grpc/ManagedChannelBuilder.html#forTarget(java.lang.String)) * [Golang](https://pkg.go.dev/google.golang.org/grpc#NewClient) **Note:** There is small variation in supported alternative resolver e.g. java support `zooKeeper` ## Motivation The main motivation is to support complex deployments with a generic custom name resolver using the interface provided by gRPC core*. **Note**: As of now only `java` and `golang` has the required interface to create custom resolver ## Detailed design The idea is to * allow a new config option to pass the [target](https://grpc.io/docs/guides/custom-name-resolution/#life-of-a-target-string) string * reduce need to create/override existing implementations to simplify use of name-resolver ### Target String Pattern* Below is an example of a custom target string which will use envoy sidecar proxy for name resolution ```text envoy://localhost:9211/flagd-sync.service ``` The custom name resolver provider in this case will use the endpoint name i.e. `flagd-sync.service` as [authority](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/nameresolve/ExampleNameResolver.java#L55-L61) and connect to `localhost:9211` ```mermaid sequenceDiagram participant application participant flagd-provider participant proxy-sidecar-agent participant flagd-sync.service application->>flagd-provider: Check the state of a feature flag flagd-provider-->>application: Get the feature flag from in-memory cache
run the evaluation logic and return final state loop flagd-provider->>flagd-provider: in-memory cache end flagd-provider->>proxy-sidecar-agent: gRPC stream connection proxy-sidecar-agent-->>flagd-provider: Note right of flagd-provider: Instead host:port target string
"envoy://localhost:9211/flagd-sync.service"
will be used proxy-sidecar-agent->>flagd-sync.service: Apply required policy and route traffic
to backend nodes flagd-sync.service-->>proxy-sidecar-agent: Note right of proxy-sidecar-agent: Policy and route rules are applied based
on `authority` header used by the
gRPC client ``` #### Drawbacks * One of the big drawback was limited support of the language only `java` and `golang` * Will introduce inconsistent user experience * Will open the door for different use cases although this can be fixed by providing sdks similar to [custom connector](https://github.com/open-feature/java-sdk-contrib/tree/main/providers/flagd#custom-connector) * ... ## Alternatives ### Option-1 Allow users to override default `authority` header as shown above in `grpcurl`, the override option was already supported by all major languages* * [Golang](https://pkg.go.dev/google.golang.org/grpc#WithAuthority) * [JAVA](https://grpc.github.io/grpc-java/javadoc/io/grpc/ForwardingChannelBuilder2.html#overrideAuthority(java.lang.String)) * [Python](https://grpc.github.io/grpc/python/glossary.html#term-channel_arguments) this option is simple and easy to implement, although it will not cover all the cases it will at least help with proxy setup where `host_header` was used to route traffic. **Ref**: Java PR: **Note**: JS, .NET, PHP still need to be explored if this options available ### Option-2 Only support the [xDS](https://grpc.io/docs/guides/custom-load-balancing/#service-mesh) protocol which already supported by gRPC core and doesn't require any custom name resolver we can simply use any `target` string with `xds://` scheme. The big benefit of this approach was it's going to be new stranded when it comes gRPC with service mesh and eliminate any custom implementation in `flagd` and the gRPC core team actively adding more features e.g. mTLS For more details refer the below document * [gRPC xDS Feature](https://grpc.github.io/grpc/core/md_doc_grpc_xds_features.html) * [gRPC xDS RFC](https://github.com/grpc/proposal/blob/master/A52-xds-custom-lb-policies.md) ### Option-3 TBD ## Unresolved questions * What to do with un-supported languages * Coming up with generic name resolver which will cover most of the cases not just proxy * ....