Fix NPE when brokers use custom priority list (#9878)

This commit is contained in:
Jian Wang 2020-06-26 17:28:54 -07:00 committed by GitHub
parent 405ebdcaaf
commit 20fd72bd13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 2 deletions

View File

@ -1484,7 +1484,7 @@ These Broker configurations can be defined in the `broker/runtime.properties` fi
|--------|---------------|-----------|-------|
|`druid.broker.balancer.type`|`random`, `connectionCount`|Determines how the broker balances connections to Historical processes. `random` choose randomly, `connectionCount` picks the process with the fewest number of active connections to|`random`|
|`druid.broker.select.tier`|`highestPriority`, `lowestPriority`, `custom`|If segments are cross-replicated across tiers in a cluster, you can tell the broker to prefer to select segments in a tier with a certain priority.|`highestPriority`|
|`druid.broker.select.tier.custom.priorities`|`An array of integer priorities.`|Select servers in tiers with a custom priority list.|None|
|`druid.broker.select.tier.custom.priorities`|`An array of integer priorities.` E.g., `[-1, 0, 1, 2]`|Select servers in tiers with a custom priority list.|The config only has effect if `druid.broker.select.tier` is set to `custom`. If `druid.broker.select.tier` is set to `custom` but this config is not specified, the effect is the same as `druid.broker.select.tier` set to `highestPriority`. Any of the integers in this config can be ignored if there's no corresponding tiers with such priorities. Tiers with priorities explicitly specified in this config always have higher priority than those not and those not specified fall back to use `highestPriority` strategy among themselves.|
##### Query prioritization and laning

View File

@ -47,7 +47,20 @@ public class CustomTierSelectorStrategy extends AbstractTierSelectorStrategy
pos++;
}
this.comparator = Comparator.comparingInt(lookup::get);
// Tiers with priorities explicitly specified in the custom priority list config always have higher priority than
// those not and those not specified fall back to use highest priority strategy among themselves
this.comparator = (p1, p2) -> {
if (lookup.containsKey(p1) && lookup.containsKey(p2)) {
return Integer.compare(lookup.get(p1), lookup.get(p2));
} else if (lookup.containsKey(p1)) {
return -1;
} else if (lookup.containsKey(p2)) {
return 1;
} else {
// Fall back to use highest priority strategy
return Integer.compare(p2, p1);
}
};
}
@Override

View File

@ -111,6 +111,80 @@ public class TierSelectorStrategyTest
);
}
@Test
public void testEmptyCustomPriorityTierSelectorStrategy()
{
DirectDruidClient client = EasyMock.createMock(DirectDruidClient.class);
QueryableDruidServer lowPriority = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, -1),
client
);
QueryableDruidServer mediumPriority = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, 0),
client
);
QueryableDruidServer highPriority = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, 1),
client
);
testTierSelectorStrategy(
new CustomTierSelectorStrategy(
new ConnectionCountServerSelectorStrategy(),
new CustomTierSelectorStrategyConfig()
{
@Override
public List<Integer> getPriorities()
{
return new ArrayList<>();
}
}
),
highPriority, mediumPriority, lowPriority
);
}
@Test
public void testIncompleteCustomPriorityTierSelectorStrategy()
{
DirectDruidClient client = EasyMock.createMock(DirectDruidClient.class);
QueryableDruidServer p0 = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, -1),
client
);
QueryableDruidServer p1 = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, 0),
client
);
QueryableDruidServer p2 = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, 1),
client
);
QueryableDruidServer p3 = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, 2),
client
);
QueryableDruidServer p4 = new QueryableDruidServer(
new DruidServer("test1", "localhost", null, 0, ServerType.HISTORICAL, DruidServer.DEFAULT_TIER, 3),
client
);
testTierSelectorStrategy(
new CustomTierSelectorStrategy(
new ConnectionCountServerSelectorStrategy(),
new CustomTierSelectorStrategyConfig()
{
@Override
public List<Integer> getPriorities()
{
return Arrays.asList(2, 0, -1);
}
}
),
p3, p1, p0, p4, p2
);
}
private void testTierSelectorStrategy(
TierSelectorStrategy tierSelectorStrategy,
QueryableDruidServer... expectedSelection