diff options
author | Martin Polden <mpolden@mpolden.no> | 2020-06-29 10:58:35 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2020-06-30 09:44:05 +0200 |
commit | dd7fda4c5ecf2234b6fabc19a8f4c7286acb337d (patch) | |
tree | 61faa325be832917bd2a759ebcfeaec69b570f90 /controller-api | |
parent | 17a43c36fa8dfb03f1a87293e02475818fbe04d7 (diff) |
Support duplicate regions within same global endpoint
To support duplicate regions within a global endpoint we create a combination of
latency and weighted alias targets.
In the following examples an application exists in `us-west-2`, `us-east-1a` and
`us-east-1b`. Before this change global endpoints pointed directly to the
zone endpoint:
```
(latency) ALIAS app1.tenant1.global.vespa.example.com -> app1.tenant1.us-west-2.vespa.example.com
(latency) ALIAS app1.tenant1.global.vespa.example.com -> app1.tenant1.us-east-1a.vespa.example.com
(latency) ALIAS app1.tenant1.global.vespa.example.com -> app1.tenant1.us-east-1b.vespa.example.com
```
After this change we introduce an additional level of names by creating a
weighted record per region:
```
(latency) ALIAS app1.tenant1.global.vespa.example.com -> app1.tenant1.us-west-2-w.vespa.example.com
|- (weighted) ALIAS app1.tenant1.us-west-2-w.vespa.example.com -> app1.tenant1.us-west-2.vespa.example.com
(latency) ALIAS app1.tenant1.global.vespa.example.com -> app1.tenant1.us-east-1-w.vespa.example.com
|- (weighted) ALIAS app1.tenant1.us-east-1-w.vespa.example.com -> app1.tenant1.us-east-1a.vespa.example.com
|- (weighted) ALIAS app1.tenant1.us-east-1-w.vespa.example.com -> app1.tenant1.us-east-1b.vespa.example.com
```
Toggling global routing status now adjusts the weight (`0 = out`) instead of
removing records as this simplified the code.
Diffstat (limited to 'controller-api')
3 files changed, 21 insertions, 7 deletions
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java index 7bd43ff1dcb..44acf1ab02e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/LatencyAliasTarget.java @@ -44,6 +44,11 @@ public class LatencyAliasTarget extends AliasTarget { return Objects.hash(super.hashCode(), zone); } + @Override + public String toString() { + return "latency target for " + name() + "[id=" + id() + ",dnsZone=" + dnsZone() + "]"; + } + /** Unpack latency alias from given record data */ public static LatencyAliasTarget unpack(RecordData data) { var parts = data.asString().split("/"); diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java index e8688b17347..03b10780e33 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/MemoryNameService.java @@ -46,9 +46,10 @@ public class MemoryNameService implements NameService { .map(d -> new Record(Record.Type.ALIAS, name, d.pack())) .collect(Collectors.toList()); // Satisfy idempotency contract of interface - records.stream() - .filter(r -> !this.records.contains(r)) - .forEach(this::add); + for (var r1 : records) { + this.records.removeIf(r2 -> conflicts(r1, r2)); + } + this.records.addAll(records); return records; } @@ -115,10 +116,13 @@ public class MemoryNameService implements NameService { * most real name services. */ private static boolean conflicts(Record r1, Record r2) { - if (!r1.name().equals(r2.name())) return false; // Distinct names never conflict - if (r1.type() == Record.Type.ALIAS && r1.type() == r2.type()) // ALIAS records only require distinct data - return r1.data().equals(r2.data()); - return true; // Anything else is considered a conflict + if (!r1.name().equals(r2.name())) return false; // Distinct names never conflict + if (r1.type() == Record.Type.ALIAS && r1.type() == r2.type()) { + AliasTarget t1 = AliasTarget.unpack(r1.data()); + AliasTarget t2 = AliasTarget.unpack(r2.data()); + return t1.name().equals(t2.name()); // ALIAS records require distinct targets + } + return true; // Anything else is considered a conflict } } diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java index 9d741cb2dbc..8f81c94257e 100644 --- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java +++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/dns/WeightedAliasTarget.java @@ -47,6 +47,11 @@ public class WeightedAliasTarget extends AliasTarget { return Objects.hash(super.hashCode(), weight); } + @Override + public String toString() { + return "weighted target for " + name() + "[id=" + id() + ",dnsZone=" + dnsZone() + ",weight=" + weight + "]"; + } + /** Unpack weighted alias from given record data */ public static WeightedAliasTarget unpack(RecordData data) { var parts = data.asString().split("/"); |