Search in sources :

Example 6 with HashRingProvider

use of com.linkedin.d2.balancer.util.hashing.HashRingProvider in project rest.li by linkedin.

the class RingBasedURIMapperTest method testNonStickyAndNonPartitioning.

@Test
public void testNonStickyAndNonPartitioning() throws ServiceUnavailableException {
    int partitionCount = 1;
    int requestPerPartition = 1000;
    int totalHostCount = 100;
    HashRingProvider ringProvider = createStaticHashRingProvider(totalHostCount, partitionCount, getHashFunction(false));
    PartitionInfoProvider infoProvider = createRangeBasedPartitionInfoProvider(partitionCount);
    URIMapper mapper = new RingBasedUriMapper(ringProvider, infoProvider);
    List<URIKeyPair<Integer>> requests = testUtil.generateRequests(partitionCount, requestPerPartition);
    URIMappingResult<Integer> results = mapper.mapUris(requests);
    Map<URI, Set<Integer>> mapping = results.getMappedKeys();
    Map<Integer, Set<Integer>> unmappedKeys = results.getUnmappedKeys();
    Map<URI, Integer> hostToPartitionId = results.getHostPartitionInfo();
    Assert.assertTrue(unmappedKeys.isEmpty());
    Assert.assertEquals(1, mapping.size());
    Assert.assertEquals(1, hostToPartitionId.size());
    Assert.assertEquals(1000, mapping.values().iterator().next().size());
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) PartitionInfoProvider(com.linkedin.d2.balancer.util.partitions.PartitionInfoProvider) URI(java.net.URI) URIKeyPair(com.linkedin.d2.balancer.util.URIKeyPair) URIMapper(com.linkedin.d2.balancer.URIMapper) Test(org.testng.annotations.Test)

Example 7 with HashRingProvider

use of com.linkedin.d2.balancer.util.hashing.HashRingProvider in project rest.li by linkedin.

the class RingBasedURIMapperTest method testMapUrisPartitionedOnly.

@Test
public void testMapUrisPartitionedOnly() throws ServiceUnavailableException {
    int partitionCount = 10;
    int requestPerPartition = 100;
    int totalHostCount = 100;
    HashRingProvider ringProvider = createStaticHashRingProvider(totalHostCount, partitionCount, getHashFunction(false));
    PartitionInfoProvider infoProvider = createRangeBasedPartitionInfoProvider(partitionCount);
    URIMapper mapper = new RingBasedUriMapper(ringProvider, infoProvider);
    List<URIKeyPair<Integer>> requests = testUtil.generateRequests(partitionCount, requestPerPartition);
    URIMappingResult<Integer> results = mapper.mapUris(requests);
    Map<URI, Set<Integer>> mapping = results.getMappedKeys();
    Map<URI, Integer> hostToPartitionId = results.getHostPartitionInfo();
    // No unmapped keys
    Assert.assertTrue(results.getUnmappedKeys().isEmpty());
    // Without sticky routing, one host should be returned for each partition
    Assert.assertEquals(10, mapping.size());
    Assert.assertEquals(10, hostToPartitionId.size());
    for (Map.Entry<URI, Integer> entry : hostToPartitionId.entrySet()) {
        // partition ids are correctly assigned for each URI
        Assert.assertTrue(entry.getKey().toString().contains(String.valueOf(entry.getValue())));
    }
    Set<Integer> mappedKeys = mapping.values().stream().reduce(new HashSet<>(), (e1, e2) -> {
        e1.addAll(e2);
        return e1;
    });
    int mappedKeyCount = mapping.values().stream().map(Set::size).reduce(Integer::sum).get();
    // Collective exhaustiveness and mutual exclusiveness
    Assert.assertEquals(partitionCount * requestPerPartition, mappedKeys.size());
    Assert.assertEquals(partitionCount * requestPerPartition, mappedKeyCount);
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) PartitionInfoProvider(com.linkedin.d2.balancer.util.partitions.PartitionInfoProvider) URI(java.net.URI) URIKeyPair(com.linkedin.d2.balancer.util.URIKeyPair) URIMapper(com.linkedin.d2.balancer.URIMapper) HashMap(java.util.HashMap) Map(java.util.Map) Test(org.testng.annotations.Test)

Example 8 with HashRingProvider

use of com.linkedin.d2.balancer.util.hashing.HashRingProvider in project rest.li by linkedin.

the class RingBasedURIMapperTest method testUniversalStickiness.

@Test
public void testUniversalStickiness() throws ServiceUnavailableException, URISyntaxException {
    int partitionCount = 4;
    int totalHostCount = 200;
    HashRingProvider ringProvider = createStaticHashRingProvider(totalHostCount, partitionCount, getHashFunction(true));
    HashFunction<Request> hashFunction = ringProvider.getRequestHashFunction(TEST_SERVICE);
    PartitionInfoProvider infoProvider = createRangeBasedPartitionInfoProvider(partitionCount);
    URIMapper mapper = new RingBasedUriMapper(ringProvider, infoProvider);
    // no partition, will be unmapped
    URIKeyPair<Integer> request1 = new URIKeyPair<>(1, new URI("d2://testService/1"));
    // partition 0
    URIKeyPair<Integer> request2 = new URIKeyPair<>(2, new URI("d2://testService/2?partition=0"));
    // partition 1
    URIKeyPair<Integer> request3 = new URIKeyPair<>(3, new URI("d2://testService/3?partition=1"));
    // partition 2
    URIKeyPair<Integer> request4 = new URIKeyPair<>(4, new URI("d2://testService/4?partition=2"));
    // partition 3
    URIKeyPair<Integer> request5 = new URIKeyPair<>(5, new URI("d2://testService/5?partition=3"));
    URIKeyPair<Integer> request6 = // partition 0 with different sticky key
    new URIKeyPair<>(6, new URI("d2://testService/6?partition=0"));
    URIKeyPair<Integer> request7 = // partition 1 with different sticky key
    new URIKeyPair<>(7, new URI("d2://testService/7?partition=1"));
    URIKeyPair<Integer> request8 = // partition 2 with different sticky key
    new URIKeyPair<>(8, new URI("d2://testService/8?partition=2"));
    URIKeyPair<Integer> request9 = // partition 3 with different sticky key
    new URIKeyPair<>(9, new URI("d2://testService/9?partition=3"));
    URIKeyPair<Integer> request10 = // with extra parameters
    new URIKeyPair<>(10, new URI("d2://testService/10?partition=0&uuid=1"));
    List<URIKeyPair<Integer>> requests = Arrays.asList(request1, request2, request3, request4, request5, request6, request7, request8, request9, request10);
    // uriMapper mapping
    URIMappingResult<Integer> uriMapperResult = mapper.mapUris(requests);
    // normal mapping
    Map<Integer, Set<Integer>> normalUnmapped = new HashMap<>();
    Map<URI, Set<Integer>> normalHostToKeySet = new HashMap<>();
    for (URIKeyPair<Integer> request : requests) {
        int partitionId = 0;
        try {
            partitionId = infoProvider.getPartitionAccessor(TEST_SERVICE).getPartitionId(request.getRequestUri());
        } catch (PartitionAccessException e) {
            normalUnmapped.computeIfAbsent(-1, k -> new HashSet<>()).add(request.getKey());
        }
        Ring<URI> ring = ringProvider.getRings(request.getRequestUri()).get(partitionId);
        URI uri = ring.get(hashFunction.hash(new URIRequest(request.getRequestUri())));
        normalHostToKeySet.computeIfAbsent(uri, k -> new HashSet<>());
        normalHostToKeySet.get(uri).add(request.getKey());
    }
    // they should have the same results
    Assert.assertEquals(uriMapperResult.getUnmappedKeys(), normalUnmapped);
    for (Map.Entry<URI, Set<Integer>> resolvedKeys : uriMapperResult.getMappedKeys().entrySet()) {
        Set<Integer> uriMapperKeySet = resolvedKeys.getValue();
        Assert.assertTrue(normalHostToKeySet.containsKey(resolvedKeys.getKey()));
        Set<Integer> normalKeySet = normalHostToKeySet.get(resolvedKeys.getKey());
        Assert.assertEquals(uriMapperKeySet, normalKeySet);
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) PartitionInfoProvider(com.linkedin.d2.balancer.util.partitions.PartitionInfoProvider) HashMap(java.util.HashMap) URIRequest(com.linkedin.d2.balancer.util.URIRequest) Request(com.linkedin.r2.message.Request) URIRequest(com.linkedin.d2.balancer.util.URIRequest) URI(java.net.URI) URIKeyPair(com.linkedin.d2.balancer.util.URIKeyPair) URIMapper(com.linkedin.d2.balancer.URIMapper) PartitionAccessException(com.linkedin.d2.balancer.util.partitions.PartitionAccessException) HashMap(java.util.HashMap) Map(java.util.Map) Test(org.testng.annotations.Test)

Example 9 with HashRingProvider

use of com.linkedin.d2.balancer.util.hashing.HashRingProvider in project rest.li by linkedin.

the class URIMapperTestUtil method createStaticHashRingProvider.

/**
 * Create {@link StaticRingProvider} for testing purpose
 */
public static HashRingProvider createStaticHashRingProvider(int totalHostCount, int partitionCount, HashFunction<Request> hashFunction) {
    int hostsPerPartition = totalHostCount / partitionCount;
    final AtomicInteger hostCounter = new AtomicInteger();
    Collection<List<Integer>> hostsIdsByPartition = IntStream.range(0, totalHostCount).boxed().collect(Collectors.groupingBy(s -> hostCounter.getAndIncrement() / hostsPerPartition)).values();
    List<Ring<URI>> rings = new ArrayList<>();
    int partiitonId = 0;
    for (List<Integer> uriList : hostsIdsByPartition) {
        int parId = partiitonId;
        Map<URI, Integer> hostMap = uriList.stream().collect(Collectors.toMap(e -> createHostURI(parId, e), e -> 100));
        Ring<URI> ring = new MPConsistentHashRing<>(hostMap);
        rings.add(ring);
        partiitonId++;
    }
    StaticRingProvider ringProvider = new StaticRingProvider(rings);
    ringProvider.setHashFunction(hashFunction);
    return ringProvider;
}
Also used : IntStream(java.util.stream.IntStream) URIKeyPair(com.linkedin.d2.balancer.util.URIKeyPair) Matchers(org.mockito.Matchers) URISyntaxException(java.net.URISyntaxException) Collection(java.util.Collection) HashBasedPartitionAccessor(com.linkedin.d2.balancer.util.partitions.HashBasedPartitionAccessor) HashBasedPartitionProperties(com.linkedin.d2.balancer.properties.HashBasedPartitionProperties) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) Mockito(org.mockito.Mockito) List(java.util.List) Matcher(java.util.regex.Matcher) Request(com.linkedin.r2.message.Request) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) URI(java.net.URI) Pattern(java.util.regex.Pattern) RangeBasedPartitionProperties(com.linkedin.d2.balancer.properties.RangeBasedPartitionProperties) PartitionInfoProvider(com.linkedin.d2.balancer.util.partitions.PartitionInfoProvider) ServiceUnavailableException(com.linkedin.d2.balancer.ServiceUnavailableException) Collections(java.util.Collections) RangeBasedPartitionAccessor(com.linkedin.d2.balancer.util.partitions.RangeBasedPartitionAccessor) ArrayList(java.util.ArrayList) URI(java.net.URI) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ArrayList(java.util.ArrayList) List(java.util.List)

Example 10 with HashRingProvider

use of com.linkedin.d2.balancer.util.hashing.HashRingProvider in project rest.li by linkedin.

the class TestRestLiScatterGather method getURIMapper.

private static URIMapper getURIMapper(boolean sticky, boolean partitioned, String regex) throws ServiceUnavailableException {
    int partitionCount = partitioned ? 10 : 1;
    int totalHostCount = 100;
    HashRingProvider ringProvider = createStaticHashRingProvider(totalHostCount, partitionCount, getHashFunction(sticky));
    PartitionInfoProvider infoProvider = createHashBasedPartitionInfoProvider(partitionCount, regex);
    return new RingBasedUriMapper(ringProvider, infoProvider);
}
Also used : HashRingProvider(com.linkedin.d2.balancer.util.hashing.HashRingProvider) URIMapperTestUtil.createStaticHashRingProvider(com.linkedin.d2.balancer.util.hashing.URIMapperTestUtil.createStaticHashRingProvider) URIMapperTestUtil.createHashBasedPartitionInfoProvider(com.linkedin.d2.balancer.util.hashing.URIMapperTestUtil.createHashBasedPartitionInfoProvider) PartitionInfoProvider(com.linkedin.d2.balancer.util.partitions.PartitionInfoProvider) RingBasedUriMapper(com.linkedin.d2.balancer.util.hashing.RingBasedUriMapper)

Aggregations

PartitionInfoProvider (com.linkedin.d2.balancer.util.partitions.PartitionInfoProvider)10 URIMapper (com.linkedin.d2.balancer.URIMapper)8 URIKeyPair (com.linkedin.d2.balancer.util.URIKeyPair)8 URI (java.net.URI)8 Test (org.testng.annotations.Test)8 HashSet (java.util.HashSet)6 Set (java.util.Set)6 Request (com.linkedin.r2.message.Request)3 Map (java.util.Map)3 URIRequest (com.linkedin.d2.balancer.util.URIRequest)2 HashMap (java.util.HashMap)2 ServiceUnavailableException (com.linkedin.d2.balancer.ServiceUnavailableException)1 HashBasedPartitionProperties (com.linkedin.d2.balancer.properties.HashBasedPartitionProperties)1 RangeBasedPartitionProperties (com.linkedin.d2.balancer.properties.RangeBasedPartitionProperties)1 HashRingProvider (com.linkedin.d2.balancer.util.hashing.HashRingProvider)1 RingBasedUriMapper (com.linkedin.d2.balancer.util.hashing.RingBasedUriMapper)1 URIMapperTestUtil.createHashBasedPartitionInfoProvider (com.linkedin.d2.balancer.util.hashing.URIMapperTestUtil.createHashBasedPartitionInfoProvider)1 URIMapperTestUtil.createStaticHashRingProvider (com.linkedin.d2.balancer.util.hashing.URIMapperTestUtil.createStaticHashRingProvider)1 HashBasedPartitionAccessor (com.linkedin.d2.balancer.util.partitions.HashBasedPartitionAccessor)1 PartitionAccessException (com.linkedin.d2.balancer.util.partitions.PartitionAccessException)1