This is an automated email from the ASF dual-hosted git repository. hulee pushed a commit to branch zooscalability in repository https://gitbox.apache.org/repos/asf/helix.git
commit 105dc0d68660d733a4a858b3ea980fcba7d20bb9 Author: Hunter Lee <[email protected]> AuthorDate: Fri Feb 28 18:47:41 2020 -0800 Make MSDS endpoint configurable for HttpRoutingDataReader (#836) We need to add a few more constructors that allows the users to configure which MSDS to talk to. Applications may wish to create RealmAwareZkClients connecting to different regions or namespaces. --- .../zookeeper/util/HttpRoutingDataReader.java | 77 ++++++++++++++++------ .../zookeeper/impl/client/TestSharedZkClient.java | 20 +++++- .../zookeeper/util/TestHttpRoutingDataReader.java | 5 +- 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/util/HttpRoutingDataReader.java b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/util/HttpRoutingDataReader.java index b795de0..04f6c44 100644 --- a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/util/HttpRoutingDataReader.java +++ b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/util/HttpRoutingDataReader.java @@ -21,6 +21,7 @@ package org.apache.helix.zookeeper.util; import java.io.IOException; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -41,13 +42,17 @@ import org.apache.http.util.EntityUtils; public class HttpRoutingDataReader { - private static final String MSDS_ENDPOINT = + private static final String SYSTEM_MSDS_ENDPOINT = System.getProperty(MetadataStoreRoutingConstants.MSDS_SERVER_ENDPOINT_KEY); private static final int HTTP_TIMEOUT_IN_MS = 5000; /** Double-checked locking requires that the following fields be volatile */ - private static volatile Map<String, List<String>> _rawRoutingData; - private static volatile MetadataStoreRoutingData _metadataStoreRoutingData; + // The following map stands for (MSDS endpoint, Raw Routing Data) + private static volatile Map<String, Map<String, List<String>>> _rawRoutingDataMap = + new HashMap<>(); + // The following map stands for (MSDS endpoint, MetadataStoreRoutingData) + private static volatile Map<String, MetadataStoreRoutingData> _metadataStoreRoutingDataMap = + new HashMap<>(); /** * This class is a Singleton. @@ -56,44 +61,78 @@ public class HttpRoutingDataReader { } /** - * Fetches routing data from the data source via HTTP. - * @return a mapping from "metadata store realm addresses" to lists of - * "metadata store sharding keys", where the sharding keys in a value list all route to - * the realm address in the key disallows a meaningful mapping to be returned + * Fetches routing data from the data source via HTTP by querying the MSDS configured in the JVM config. + * @return + * @throws IOException */ public static Map<String, List<String>> getRawRoutingData() throws IOException { - if (MSDS_ENDPOINT == null || MSDS_ENDPOINT.isEmpty()) { + if (SYSTEM_MSDS_ENDPOINT == null || SYSTEM_MSDS_ENDPOINT.isEmpty()) { throw new IllegalStateException( "HttpRoutingDataReader was unable to find a valid MSDS endpoint String in System Properties!"); } - if (_rawRoutingData == null) { + return getRawRoutingData(SYSTEM_MSDS_ENDPOINT); + } + + /** + * Fetches routing data from the data source via HTTP. + * @return a mapping from "metadata store realm addresses" to lists of + * "metadata store sharding keys", where the sharding keys in a value list all route to + * the realm address in the key disallows a meaningful mapping to be returned. + * @param msdsEndpoint Metadata Store Directory Store endpoint to query from + */ + public static Map<String, List<String>> getRawRoutingData(String msdsEndpoint) + throws IOException { + Map<String, List<String>> rawRoutingData = _rawRoutingDataMap.get(msdsEndpoint); + if (rawRoutingData == null) { synchronized (HttpRoutingDataReader.class) { - if (_rawRoutingData == null) { + rawRoutingData = _rawRoutingDataMap.get(msdsEndpoint); + if (rawRoutingData == null) { String routingDataJson = getAllRoutingData(); // Update the reference if reading routingData over HTTP is successful - _rawRoutingData = parseRoutingData(routingDataJson); + rawRoutingData = parseRoutingData(routingDataJson); + _rawRoutingDataMap.put(msdsEndpoint, rawRoutingData); } } } - return _rawRoutingData; + return rawRoutingData; + } + + /** + * Returns the routing data read from MSDS in a MetadataStoreRoutingData format by querying the MSDS configured in the JVM config. + * @return MetadataStoreRoutingData + * @throws IOException + * @throws InvalidRoutingDataException + */ + public static MetadataStoreRoutingData getMetadataStoreRoutingData() + throws IOException, InvalidRoutingDataException { + if (SYSTEM_MSDS_ENDPOINT == null || SYSTEM_MSDS_ENDPOINT.isEmpty()) { + throw new IllegalStateException( + "HttpRoutingDataReader was unable to find a valid MSDS endpoint String in System Properties!"); + } + return getMetadataStoreRoutingData(SYSTEM_MSDS_ENDPOINT); } /** * Returns the routing data read from MSDS in a MetadataStoreRoutingData format. - * @return + * @param msdsEndpoint Metadata Store Directory Store endpoint to query from + * @return MetadataStoreRoutingData * @throws IOException if there is an issue connecting to MSDS * @throws InvalidRoutingDataException if the raw routing data is not valid */ - public static MetadataStoreRoutingData getMetadataStoreRoutingData() + public static MetadataStoreRoutingData getMetadataStoreRoutingData(String msdsEndpoint) throws IOException, InvalidRoutingDataException { - if (_metadataStoreRoutingData == null) { + MetadataStoreRoutingData metadataStoreRoutingData = + _metadataStoreRoutingDataMap.get(msdsEndpoint); + if (metadataStoreRoutingData == null) { synchronized (HttpRoutingDataReader.class) { - if (_metadataStoreRoutingData == null) { - _metadataStoreRoutingData = new TrieRoutingData(getRawRoutingData()); + metadataStoreRoutingData = _metadataStoreRoutingDataMap.get(msdsEndpoint); + if (metadataStoreRoutingData == null) { + metadataStoreRoutingData = new TrieRoutingData(getRawRoutingData(msdsEndpoint)); + _metadataStoreRoutingDataMap.put(msdsEndpoint, metadataStoreRoutingData); } } } - return _metadataStoreRoutingData; + return metadataStoreRoutingData; } /** @@ -105,7 +144,7 @@ public class HttpRoutingDataReader { // Note that MSDS_ENDPOINT should provide high-availability - it risks becoming a single point of failure if it's backed by a single IP address/host // Retry count is 3 by default. HttpGet requestAllData = new HttpGet( - MSDS_ENDPOINT + MetadataStoreRoutingConstants.MSDS_GET_ALL_ROUTING_DATA_ENDPOINT); + SYSTEM_MSDS_ENDPOINT + MetadataStoreRoutingConstants.MSDS_GET_ALL_ROUTING_DATA_ENDPOINT); // Define timeout configs RequestConfig config = RequestConfig.custom().setConnectTimeout(HTTP_TIMEOUT_IN_MS) diff --git a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestSharedZkClient.java b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestSharedZkClient.java index 364f66f..1dd44f6 100644 --- a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestSharedZkClient.java +++ b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestSharedZkClient.java @@ -1,8 +1,26 @@ package org.apache.helix.zookeeper.impl.client; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + import org.apache.helix.zookeeper.datamodel.ZNRecord; import org.apache.helix.zookeeper.datamodel.serializer.ZNRecordSerializer; -import org.apache.helix.zookeeper.impl.factory.DedicatedZkClientFactory; import org.apache.helix.zookeeper.impl.factory.SharedZkClientFactory; import org.apache.zookeeper.CreateMode; import org.testng.Assert; diff --git a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestHttpRoutingDataReader.java b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestHttpRoutingDataReader.java index 83ee471..1eccd1a 100644 --- a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestHttpRoutingDataReader.java +++ b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/util/TestHttpRoutingDataReader.java @@ -87,9 +87,8 @@ public class TestHttpRoutingDataReader extends ZkTestBase { Map<String, Set<String>> groupedMappings = allMappings.entrySet().stream().collect(Collectors .groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toSet()))); - _testRawRoutingData.forEach((realm, keys) -> { - Assert.assertEquals(groupedMappings.get(realm), new HashSet(keys)); - }); + _testRawRoutingData.forEach( + (realm, keys) -> Assert.assertEquals(groupedMappings.get(realm), new HashSet(keys))); } /**
