YARN-8333. Load balance YARN services using RegistryDNS multiple A records. Contributed by Eric Yang
This commit is contained in:
parent
6468071f13
commit
6bc92e304f
@ -290,6 +290,26 @@ protected Name getContainerName()
|
|||||||
domain));
|
domain));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the DNS name constructed from the component name.
|
||||||
|
*
|
||||||
|
* @return the DNS naem.
|
||||||
|
* @throws PathNotFoundException
|
||||||
|
* @throws TextParseException
|
||||||
|
*/
|
||||||
|
protected Name getComponentName()
|
||||||
|
throws PathNotFoundException, TextParseException {
|
||||||
|
String service = RegistryPathUtils.lastPathEntry(
|
||||||
|
RegistryPathUtils.parentOf(RegistryPathUtils.parentOf(getPath())));
|
||||||
|
String component = getRecord().get("yarn:component").toLowerCase();
|
||||||
|
String user = RegistryPathUtils.getUsername(getPath());
|
||||||
|
return Name.fromString(MessageFormat.format("{0}.{1}.{2}.{3}",
|
||||||
|
component,
|
||||||
|
service,
|
||||||
|
user,
|
||||||
|
domain));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -242,7 +242,8 @@ public AContainerRecordDescriptor(String path,
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
this.setTarget(InetAddress.getByName(ip));
|
this.setTarget(InetAddress.getByName(ip));
|
||||||
this.setNames(new Name[] {getContainerName(), getContainerIDName()});
|
this.setNames(new Name[] {getContainerName(), getContainerIDName(),
|
||||||
|
getComponentName()});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
|
@ -115,32 +115,47 @@ public class TestRegistryDNS extends Assert {
|
|||||||
+ "}\n";
|
+ "}\n";
|
||||||
static final String CONTAINER_RECORD = "{\n"
|
static final String CONTAINER_RECORD = "{\n"
|
||||||
+ " \"type\" : \"JSONServiceRecord\",\n"
|
+ " \"type\" : \"JSONServiceRecord\",\n"
|
||||||
+ " \"description\" : \"COMP-NAME\",\n"
|
+ " \"description\" : \"httpd-1\",\n"
|
||||||
+ " \"external\" : [ ],\n"
|
+ " \"external\" : [ ],\n"
|
||||||
+ " \"internal\" : [ ],\n"
|
+ " \"internal\" : [ ],\n"
|
||||||
+ " \"yarn:id\" : \"container_e50_1451931954322_0016_01_000002\",\n"
|
+ " \"yarn:id\" : \"container_e50_1451931954322_0016_01_000002\",\n"
|
||||||
+ " \"yarn:persistence\" : \"container\",\n"
|
+ " \"yarn:persistence\" : \"container\",\n"
|
||||||
+ " \"yarn:ip\" : \"172.17.0.19\",\n"
|
+ " \"yarn:ip\" : \"172.17.0.19\",\n"
|
||||||
+ " \"yarn:hostname\" : \"0a134d6329ba\"\n"
|
+ " \"yarn:hostname\" : \"host1\",\n"
|
||||||
|
+ " \"yarn:component\" : \"httpd\"\n"
|
||||||
|
+ "}\n";
|
||||||
|
|
||||||
|
static final String CONTAINER_RECORD2 = "{\n"
|
||||||
|
+ " \"type\" : \"JSONServiceRecord\",\n"
|
||||||
|
+ " \"description\" : \"httpd-2\",\n"
|
||||||
|
+ " \"external\" : [ ],\n"
|
||||||
|
+ " \"internal\" : [ ],\n"
|
||||||
|
+ " \"yarn:id\" : \"container_e50_1451931954322_0016_01_000003\",\n"
|
||||||
|
+ " \"yarn:persistence\" : \"container\",\n"
|
||||||
|
+ " \"yarn:ip\" : \"172.17.0.20\",\n"
|
||||||
|
+ " \"yarn:hostname\" : \"host2\",\n"
|
||||||
|
+ " \"yarn:component\" : \"httpd\"\n"
|
||||||
+ "}\n";
|
+ "}\n";
|
||||||
|
|
||||||
private static final String CONTAINER_RECORD_NO_IP = "{\n"
|
private static final String CONTAINER_RECORD_NO_IP = "{\n"
|
||||||
+ " \"type\" : \"JSONServiceRecord\",\n"
|
+ " \"type\" : \"JSONServiceRecord\",\n"
|
||||||
+ " \"description\" : \"COMP-NAME\",\n"
|
+ " \"description\" : \"httpd-1\",\n"
|
||||||
+ " \"external\" : [ ],\n"
|
+ " \"external\" : [ ],\n"
|
||||||
+ " \"internal\" : [ ],\n"
|
+ " \"internal\" : [ ],\n"
|
||||||
+ " \"yarn:id\" : \"container_e50_1451931954322_0016_01_000002\",\n"
|
+ " \"yarn:id\" : \"container_e50_1451931954322_0016_01_000002\",\n"
|
||||||
+ " \"yarn:persistence\" : \"container\"\n"
|
+ " \"yarn:persistence\" : \"container\",\n"
|
||||||
|
+ " \"yarn:component\" : \"httpd\"\n"
|
||||||
+ "}\n";
|
+ "}\n";
|
||||||
|
|
||||||
private static final String CONTAINER_RECORD_YARN_PERSISTANCE_ABSENT = "{\n"
|
private static final String CONTAINER_RECORD_YARN_PERSISTANCE_ABSENT = "{\n"
|
||||||
+ " \"type\" : \"JSONServiceRecord\",\n"
|
+ " \"type\" : \"JSONServiceRecord\",\n"
|
||||||
+ " \"description\" : \"COMP-NAME\",\n"
|
+ " \"description\" : \"httpd-1\",\n"
|
||||||
+ " \"external\" : [ ],\n"
|
+ " \"external\" : [ ],\n"
|
||||||
+ " \"internal\" : [ ],\n"
|
+ " \"internal\" : [ ],\n"
|
||||||
+ " \"yarn:id\" : \"container_e50_1451931954322_0016_01_000003\",\n"
|
+ " \"yarn:id\" : \"container_e50_1451931954322_0016_01_000003\",\n"
|
||||||
+ " \"yarn:ip\" : \"172.17.0.19\",\n"
|
+ " \"yarn:ip\" : \"172.17.0.19\",\n"
|
||||||
+ " \"yarn:hostname\" : \"0a134d6329bb\"\n"
|
+ " \"yarn:hostname\" : \"0a134d6329bb\",\n"
|
||||||
|
+ " \"yarn:component\" : \"httpd\""
|
||||||
+ "}\n";
|
+ "}\n";
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@ -229,7 +244,7 @@ public void testContainerRegistration() throws Exception {
|
|||||||
assertEquals("wrong result", "172.17.0.19",
|
assertEquals("wrong result", "172.17.0.19",
|
||||||
((ARecord) recs[0]).getAddress().getHostAddress());
|
((ARecord) recs[0]).getAddress().getHostAddress());
|
||||||
|
|
||||||
recs = assertDNSQuery("comp-name.test1.root.dev.test.", 1);
|
recs = assertDNSQuery("httpd-1.test1.root.dev.test.", 1);
|
||||||
assertTrue("not an ARecord", recs[0] instanceof ARecord);
|
assertTrue("not an ARecord", recs[0] instanceof ARecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +283,7 @@ public void testRecordTTL() throws Exception {
|
|||||||
((ARecord) recs[0]).getAddress().getHostAddress());
|
((ARecord) recs[0]).getAddress().getHostAddress());
|
||||||
assertEquals("wrong ttl", 30L, recs[0].getTTL());
|
assertEquals("wrong ttl", 30L, recs[0].getTTL());
|
||||||
|
|
||||||
recs = assertDNSQuery("comp-name.test1.root.dev.test.", 1);
|
recs = assertDNSQuery("httpd-1.test1.root.dev.test.", 1);
|
||||||
assertTrue("not an ARecord", recs[0] instanceof ARecord);
|
assertTrue("not an ARecord", recs[0] instanceof ARecord);
|
||||||
|
|
||||||
assertEquals("wrong ttl", 30L, recs[0].getTTL());
|
assertEquals("wrong ttl", 30L, recs[0].getTTL());
|
||||||
@ -286,7 +301,7 @@ public void testReverseLookup() throws Exception {
|
|||||||
// start assessing whether correct records are available
|
// start assessing whether correct records are available
|
||||||
Record[] recs = assertDNSQuery("19.0.17.172.in-addr.arpa.", Type.PTR, 1);
|
Record[] recs = assertDNSQuery("19.0.17.172.in-addr.arpa.", Type.PTR, 1);
|
||||||
assertEquals("wrong result",
|
assertEquals("wrong result",
|
||||||
"comp-name.test1.root.dev.test.",
|
"httpd-1.test1.root.dev.test.",
|
||||||
((PTRRecord) recs[0]).getTarget().toString());
|
((PTRRecord) recs[0]).getTarget().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,7 +327,7 @@ public void testReverseLookupInLargeNetwork() throws Exception {
|
|||||||
// start assessing whether correct records are available
|
// start assessing whether correct records are available
|
||||||
Record[] recs = assertDNSQuery("19.0.17.172.in-addr.arpa.", Type.PTR, 1);
|
Record[] recs = assertDNSQuery("19.0.17.172.in-addr.arpa.", Type.PTR, 1);
|
||||||
assertEquals("wrong result",
|
assertEquals("wrong result",
|
||||||
"comp-name.test1.root.dev.test.",
|
"httpd-1.test1.root.dev.test.",
|
||||||
((PTRRecord) recs[0]).getTarget().toString());
|
((PTRRecord) recs[0]).getTarget().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,7 +505,7 @@ public void testAAAALookup() throws Exception {
|
|||||||
assertEquals("wrong result", "172.17.0.19",
|
assertEquals("wrong result", "172.17.0.19",
|
||||||
((AAAARecord) recs[0]).getAddress().getHostAddress());
|
((AAAARecord) recs[0]).getAddress().getHostAddress());
|
||||||
|
|
||||||
recs = assertDNSQuery("comp-name.test1.root.dev.test.", Type.AAAA, 1);
|
recs = assertDNSQuery("httpd-1.test1.root.dev.test.", Type.AAAA, 1);
|
||||||
assertTrue("not an ARecord", recs[0] instanceof AAAARecord);
|
assertTrue("not an ARecord", recs[0] instanceof AAAARecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,13 +580,13 @@ public void testReadMasterFile() throws Exception {
|
|||||||
assertEquals("wrong result", "172.17.0.19",
|
assertEquals("wrong result", "172.17.0.19",
|
||||||
((ARecord) recs[0]).getAddress().getHostAddress());
|
((ARecord) recs[0]).getAddress().getHostAddress());
|
||||||
|
|
||||||
recs = assertDNSQuery("comp-name.test1.root.dev.test.", 1);
|
recs = assertDNSQuery("httpd-1.test1.root.dev.test.", 1);
|
||||||
assertTrue("not an ARecord", recs[0] instanceof ARecord);
|
assertTrue("not an ARecord", recs[0] instanceof ARecord);
|
||||||
|
|
||||||
// lookup dyanmic reverse records
|
// lookup dyanmic reverse records
|
||||||
recs = assertDNSQuery("19.0.17.172.in-addr.arpa.", Type.PTR, 1);
|
recs = assertDNSQuery("19.0.17.172.in-addr.arpa.", Type.PTR, 1);
|
||||||
assertEquals("wrong result",
|
assertEquals("wrong result",
|
||||||
"comp-name.test1.root.dev.test.",
|
"httpd-1.test1.root.dev.test.",
|
||||||
((PTRRecord) recs[0]).getTarget().toString());
|
((PTRRecord) recs[0]).getTarget().toString());
|
||||||
|
|
||||||
// now lookup static reverse records
|
// now lookup static reverse records
|
||||||
@ -649,6 +664,27 @@ public void testExternalCNAMERecord() throws Exception {
|
|||||||
assertDNSQueryNotNull("mail.yahoo.com.", Type.CNAME);
|
assertDNSQueryNotNull("mail.yahoo.com.", Type.CNAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiARecord() throws Exception {
|
||||||
|
ServiceRecord record = getMarshal().fromBytes("somepath",
|
||||||
|
CONTAINER_RECORD.getBytes());
|
||||||
|
ServiceRecord record2 = getMarshal().fromBytes("somepath",
|
||||||
|
CONTAINER_RECORD2.getBytes());
|
||||||
|
getRegistryDNS().register(
|
||||||
|
"/registry/users/root/services/org-apache-slider/test1/components/"
|
||||||
|
+ "ctr-e50-1451931954322-0016-01-000002",
|
||||||
|
record);
|
||||||
|
getRegistryDNS().register(
|
||||||
|
"/registry/users/root/services/org-apache-slider/test1/components/"
|
||||||
|
+ "ctr-e50-1451931954322-0016-01-000003",
|
||||||
|
record2);
|
||||||
|
|
||||||
|
// start assessing whether correct records are available
|
||||||
|
Record[] recs =
|
||||||
|
assertDNSQuery("httpd.test1.root.dev.test.", 2);
|
||||||
|
assertTrue("not an ARecord", recs[0] instanceof ARecord);
|
||||||
|
assertTrue("not an ARecord", recs[1] instanceof ARecord);
|
||||||
|
}
|
||||||
public RegistryDNS getRegistryDNS() {
|
public RegistryDNS getRegistryDNS() {
|
||||||
return registryDNS;
|
return registryDNS;
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,18 @@ Note that YARN service framework assigns `COMPONENT_INSTANCE_NAME` for each cont
|
|||||||
assigned `0` since it is the first and only instance for the `hbasemaster` component. In case of `regionserver` component, it can have multiple containers
|
assigned `0` since it is the first and only instance for the `hbasemaster` component. In case of `regionserver` component, it can have multiple containers
|
||||||
and so be named as such: `regionserver-0`, `regionserver-1`, `regionserver-2` ... etc
|
and so be named as such: `regionserver-0`, `regionserver-1`, `regionserver-2` ... etc
|
||||||
|
|
||||||
|
Each YARN service component also has Multi-A Records for container fault tolerance or load balancing via RegistryDNS. The naming format is defined as:
|
||||||
|
```
|
||||||
|
${COMPONENT_NAME}.${SERVICE_NAME}.${USER}.${DOMAIN}
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, a component named www for application app launched by Chuck with 3 containers will have DNS records that look like:
|
||||||
|
```
|
||||||
|
www.app.chuck.example.com IN A 123.123.123.1
|
||||||
|
www.app.chuck.example.com IN A 123.123.123.1
|
||||||
|
www.app.chuck.example.com IN A 123.123.123.1
|
||||||
|
```
|
||||||
|
|
||||||
`Disclaimer`: The DNS implementation is still experimental. It should not be used as a fully-functional DNS.
|
`Disclaimer`: The DNS implementation is still experimental. It should not be used as a fully-functional DNS.
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user