grpc / grpc-java

The Java gRPC implementation. HTTP/2 based RPC
https://grpc.io/docs/languages/java/
Apache License 2.0
11.37k stars 3.82k forks source link

DNS+SRV NameResolver #2109

Open lburgazzoli opened 8 years ago

lburgazzoli commented 8 years ago

I see that there is currently a dns name resolver and I'm wondering if a dns+srv resolver would make sense for the project:

So you would be able to resolve a target like:

"dns+srv:///_etcd-server._tcp.example.com"
bobymicroby commented 8 years ago

👍

rsmilyanov commented 8 years ago

:+1:

ejona86 commented 8 years ago

We've talked about doing SRV (and TXT). I know we didn't have a pressing need for it, but we were including it in the design. @zhangkun83, do you know the status of that stuff?

zhangkun83 commented 8 years ago

I don't think anything has been done about it.

What exactly would such a resolver do? Take "dns+srv:///_etcd-server._tcp.example.com" for example, would it fetch the SRV recrod for "example.com" and hand over the target etcd:///<resolved-target> to an etcd NameResolver?

lburgazzoli commented 8 years ago

I would return a list of IPs and ports associated to _etcd-server._tcp.example.com, i.e.:

$ dig +noall +answer SRV _etcd-server._tcp.example.com
_etcd-server._tcp.example.com. 300 IN  SRV  0 0 2380 infra0.example.com.
_etcd-server._tcp.example.com. 300 IN  SRV  0 0 2380 infra1.example.com.
_etcd-server._tcp.example.com. 300 IN  SRV  0 0 2380 infra2.example.com.

So you know that you have 3 etcd servers you can use for load balancing:

zhangkun83 commented 8 years ago

infra0.example.com are host names, not IPs. They will need a second resolution to become IPs. Under the current NameResolver interface, if we get N SRV records, we will need to create N DnsNameResolvers to resolve these host names. It's doable.

I was concerned at first because I thought the NameResolver would also need to act as an etcd client. Now I guess it's not the case. If we changed the example to "dns+srv:///_foo-server._tcp.example.com" it would be less confusing. So the final product of name resolution is a bunch of socket addresses to foo servers. We probably should treat the IP addresses resolved from a SRV target as equivalent addresses, and LoadBalancer may choose to round-robin throughout these SRV targets.

lburgazzoli commented 8 years ago

Ah yep sorry, I've used etcd because I'm working on it so it was the first example I had in mind. The srv record may use IPs instead of host names and may provide a priority too.

ejona86 commented 8 years ago

If there are no SRV records, then we should probably contact example.com. It may make sense to use dns:///example.com?service=foo-server.

lburgazzoli commented 8 years ago

I'm unsure about that as if you do not have any record it would mean you do not have any service registered (i.e. in a kubernetes cluster) or a configuration issue (i.e. in a standard environment) and that would indicate a problem.

I would prefer to fail here and maybe have an optional retry strategy that would force a new resolution if no hosts are returned.

ejona86 commented 8 years ago

Before we discuss too much more, I wanted to mention that this will probably need some agreement from the other languages.

I was going for the recommendation in RFC2782:

A SRV-cognizant client SHOULD use this procedure to locate a list of servers and connect to the preferred one:

    Do a lookup for QNAME=_service._protocol.target, QCLASS=IN,
    QTYPE=SRV.

    If the reply is NOERROR, ANCOUNT>0 and there is at least one
    SRV RR which specifies the requested Service and Protocol in
    the reply:
       <snip>
    else

       Do a lookup for QNAME=target, QCLASS=IN, QTYPE=A

But I admit it was written before SRV saw widespread use and also writes:

  • Future protocols could be designed to use SRV RR lookups as the means by which clients locate their servers.

There are probably different users of grpc that would want each behavior. So we may need a way to distinguish between them.

Looking at this more, since "service" in SRV is actually the same as /etc/services and the port, then we really don't need a different syntax: dns:///example.com:etcd-server.

That host:service syntax is supported by applications using getaddrinfo (which allows things like curl https://example.com:https/), but it is a bit weird for Java which doesn't provide a service name → port number lookup. It would work fine in all the other implementations though, including Go.

I could understand concern for looking up SRV records all the time, thus I could understand having dns+srv:///example.com:etcd-server to signal SRV querying. A query parameter could disable/enable fallback. I don't know if it should fallback to normal DNS resolution by default though.

ejona86 commented 8 years ago

SRV example for myself:

import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;

public class Srv {
  public static void main(String[] args) throws Exception {
    InitialDirContext ctx = new InitialDirContext();
    Attribute attr = ctx.getAttributes("dns:///_xmpp-server._tcp.google.com", new String[] {"SRV"})
        .get("SRV");
    for (int i = 0; i < attr.size(); i++) {
      String s = (String) attr.get(i);
      System.out.println(s);
    }
  }
}
lburgazzoli commented 8 years ago

@ejona86

I'm quite fine with the syntax dns:///example.com:etcd-server, best would be as you said if the dns resolver could support both queries by setting up appropriate parameter (same thing for fallback).

However I would like to support also the form of _service._protocol.target as this info may be provided from an external source (i.e. an environment variable) so a DnsSrvNameResolverprovider could be created whose goal is to create a DnsNameResover properly configured to do srv lookup.

Make sense ?

lburgazzoli commented 7 years ago

any progress on this ?

zhangkun83 commented 7 years ago

@lburgazzoli no progress so far. This doesn't seem to be a high priority so we have been working on more urgent stuff.

carl-mastrangelo commented 7 years ago

TXT (and maybe SRV) is needed for service config, so this should be a higher priority.

zhangkun83 commented 7 years ago

Service config in DNS is proposed in https://github.com/grpc/proposal/pull/5