Skip to content

Commit c5e6d82

Browse files
authored
HBASE-28425 Allow specify cluster key without zookeeper in replication (#5865)
Signed-off-by: Nick Dimiduk <[email protected]> Reviewed-by: Andor Molnár <[email protected]>
1 parent 65ff7a2 commit c5e6d82

File tree

54 files changed

+352
-178
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+352
-178
lines changed

hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionRegistryFactory.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
import java.io.IOException;
2121
import java.net.URI;
22+
import java.net.URISyntaxException;
23+
import java.util.Locale;
2224
import java.util.ServiceLoader;
2325
import org.apache.commons.lang3.StringUtils;
2426
import org.apache.hadoop.conf.Configuration;
@@ -35,7 +37,7 @@
3537
* The entry point for creating a {@link ConnectionRegistry}.
3638
*/
3739
@InterfaceAudience.Private
38-
final class ConnectionRegistryFactory {
40+
public final class ConnectionRegistryFactory {
3941

4042
private static final Logger LOG = LoggerFactory.getLogger(ConnectionRegistryFactory.class);
4143

@@ -90,4 +92,46 @@ static ConnectionRegistry create(Configuration conf, User user) {
9092
RpcConnectionRegistry.class, ConnectionRegistry.class);
9193
return ReflectionUtils.newInstance(clazz, conf, user);
9294
}
95+
96+
/**
97+
* Check whether the given {@code uri} is valid.
98+
* <p/>
99+
* Notice that there is no fallback logic for this method, so passing an URI with null scheme can
100+
* not pass.
101+
* @throws IOException if this is not a valid connection registry URI
102+
*/
103+
public static void validate(URI uri) throws IOException {
104+
if (StringUtils.isBlank(uri.getScheme())) {
105+
throw new IOException("No schema for uri: " + uri);
106+
}
107+
ConnectionRegistryURIFactory factory = FACTORIES.get(uri.getScheme().toLowerCase(Locale.ROOT));
108+
if (factory == null) {
109+
throw new IOException(
110+
"No factory registered for scheme " + uri.getScheme() + ", uri: " + uri);
111+
}
112+
factory.validate(uri);
113+
}
114+
115+
/**
116+
* If the given {@code clusterKey} can be parsed to a {@link URI}, and the scheme of the
117+
* {@link URI} is supported by us, return the {@link URI}, otherwise return {@code null}.
118+
* @param clusterKey the cluster key, typically from replication peer config
119+
* @return a {@link URI} or {@code null}.
120+
*/
121+
public static URI tryParseAsConnectionURI(String clusterKey) {
122+
// The old cluster key format may not be parsed as URI if we use ip address as the zookeeper
123+
// address, so here we need to catch the URISyntaxException and return false
124+
URI uri;
125+
try {
126+
uri = new URI(clusterKey);
127+
} catch (URISyntaxException e) {
128+
LOG.debug("failed to parse cluster key to URI: {}", clusterKey, e);
129+
return null;
130+
}
131+
if (FACTORIES.containsKey(uri.getScheme())) {
132+
return uri;
133+
} else {
134+
return null;
135+
}
136+
}
93137
}

hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionRegistryURIFactory.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,10 @@ public interface ConnectionRegistryURIFactory {
3939
* {@link ConnectionRegistryFactory}.
4040
*/
4141
String getScheme();
42+
43+
/**
44+
* Validate the given {@code uri}.
45+
* @throws IOException if this is not a valid connection registry URI.
46+
*/
47+
void validate(URI uri) throws IOException;
4248
}

hbase-client/src/main/java/org/apache/hadoop/hbase/client/RawAsyncHBaseAdmin.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import edu.umd.cs.findbugs.annotations.Nullable;
2626
import java.io.IOException;
27+
import java.net.URI;
2728
import java.util.ArrayList;
2829
import java.util.Arrays;
2930
import java.util.Collections;
@@ -3785,15 +3786,17 @@ private CompletableFuture<Void> checkAndSyncTableToPeerClusters(TableName tableN
37853786

37863787
private CompletableFuture<Void> trySyncTableToPeerCluster(TableName tableName, byte[][] splits,
37873788
ReplicationPeerDescription peer) {
3788-
Configuration peerConf = null;
3789+
Configuration peerConf;
37893790
try {
3790-
peerConf =
3791-
ReplicationPeerConfigUtil.getPeerClusterConfiguration(connection.getConfiguration(), peer);
3791+
peerConf = ReplicationPeerConfigUtil
3792+
.getPeerClusterConfiguration(connection.getConfiguration(), peer.getPeerConfig());
37923793
} catch (IOException e) {
37933794
return failedFuture(e);
37943795
}
3796+
URI connectionUri =
3797+
ConnectionRegistryFactory.tryParseAsConnectionURI(peer.getPeerConfig().getClusterKey());
37953798
CompletableFuture<Void> future = new CompletableFuture<>();
3796-
addListener(ConnectionFactory.createAsyncConnection(peerConf), (conn, err) -> {
3799+
addListener(ConnectionFactory.createAsyncConnection(connectionUri, peerConf), (conn, err) -> {
37973800
if (err != null) {
37983801
future.completeExceptionally(err);
37993802
return;

hbase-client/src/main/java/org/apache/hadoop/hbase/client/RpcConnectionRegistryURIFactory.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.io.IOException;
2121
import java.net.URI;
22+
import org.apache.commons.lang3.StringUtils;
2223
import org.apache.hadoop.conf.Configuration;
2324
import org.apache.hadoop.hbase.security.User;
2425
import org.apache.yetus.audience.InterfaceAudience;
@@ -46,4 +47,12 @@ public ConnectionRegistry create(URI uri, Configuration conf, User user) throws
4647
public String getScheme() {
4748
return "hbase+rpc";
4849
}
50+
51+
@Override
52+
public void validate(URI uri) throws IOException {
53+
if (StringUtils.isBlank(uri.getAuthority())) {
54+
throw new IOException("no bootstrap nodes specified, uri: " + uri);
55+
}
56+
// TODO: add more check about the bootstrap nodes
57+
}
4958
}

hbase-client/src/main/java/org/apache/hadoop/hbase/client/ZKConnectionRegistryURIFactory.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.io.IOException;
2121
import java.net.URI;
22+
import org.apache.commons.lang3.StringUtils;
2223
import org.apache.hadoop.conf.Configuration;
2324
import org.apache.hadoop.hbase.HConstants;
2425
import org.apache.hadoop.hbase.security.User;
@@ -49,4 +50,15 @@ public ConnectionRegistry create(URI uri, Configuration conf, User user) throws
4950
public String getScheme() {
5051
return "hbase+zk";
5152
}
53+
54+
@Override
55+
public void validate(URI uri) throws IOException {
56+
if (StringUtils.isBlank(uri.getAuthority())) {
57+
throw new IOException("no zookeeper quorum specified, uri: " + uri);
58+
}
59+
// TODO: add more check about the zookeeper quorum
60+
if (StringUtils.isBlank(uri.getPath())) {
61+
throw new IOException("no zookeeper parent path specified, uri: " + uri);
62+
}
63+
}
5264
}

hbase-client/src/main/java/org/apache/hadoop/hbase/client/replication/ReplicationPeerConfigUtil.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.hadoop.hbase.CompoundConfiguration;
3333
import org.apache.hadoop.hbase.HBaseConfiguration;
3434
import org.apache.hadoop.hbase.TableName;
35+
import org.apache.hadoop.hbase.client.ConnectionRegistryFactory;
3536
import org.apache.hadoop.hbase.exceptions.DeserializationException;
3637
import org.apache.hadoop.hbase.replication.ReplicationException;
3738
import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
@@ -629,19 +630,19 @@ public static ReplicationPeerConfig removeExcludeTableCFsFromReplicationPeerConf
629630

630631
/**
631632
* Returns the configuration needed to talk to the remote slave cluster.
632-
* @param conf the base configuration
633-
* @param peer the description of replication peer
633+
* @param conf the base configuration
634+
* @param peerConfig the peer config of replication peer
634635
* @return the configuration for the peer cluster, null if it was unable to get the configuration
635636
* @throws IOException when create peer cluster configuration failed
636637
*/
637638
public static Configuration getPeerClusterConfiguration(Configuration conf,
638-
ReplicationPeerDescription peer) throws IOException {
639-
ReplicationPeerConfig peerConfig = peer.getPeerConfig();
639+
ReplicationPeerConfig peerConfig) throws IOException {
640640
Configuration otherConf;
641-
try {
641+
if (ConnectionRegistryFactory.tryParseAsConnectionURI(peerConfig.getClusterKey()) != null) {
642+
otherConf = HBaseConfiguration.create(conf);
643+
} else {
644+
// only need to apply cluster key for old style cluster key
642645
otherConf = HBaseConfiguration.createClusterConf(conf, peerConfig.getClusterKey());
643-
} catch (IOException e) {
644-
throw new IOException("Can't get peer configuration for peerId=" + peer.getPeerId(), e);
645646
}
646647

647648
if (!peerConfig.getConfiguration().isEmpty()) {

hbase-common/src/main/java/org/apache/hadoop/hbase/HBaseConfiguration.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import java.io.IOException;
2121
import java.util.Map;
22+
import org.apache.commons.lang3.StringUtils;
2223
import org.apache.hadoop.conf.Configuration;
2324
import org.apache.hadoop.hbase.util.VersionInfo;
2425
import org.apache.hadoop.hbase.zookeeper.ZKConfig;
@@ -226,11 +227,11 @@ public static Configuration createClusterConf(Configuration baseConf, String clu
226227
public static Configuration createClusterConf(Configuration baseConf, String clusterKey,
227228
String overridePrefix) throws IOException {
228229
Configuration clusterConf = HBaseConfiguration.create(baseConf);
229-
if (clusterKey != null && !clusterKey.isEmpty()) {
230+
if (!StringUtils.isBlank(clusterKey)) {
230231
applyClusterKeyToConf(clusterConf, clusterKey);
231232
}
232233

233-
if (overridePrefix != null && !overridePrefix.isEmpty()) {
234+
if (!StringUtils.isBlank(overridePrefix)) {
234235
Configuration clusterSubset = HBaseConfiguration.subset(clusterConf, overridePrefix);
235236
HBaseConfiguration.merge(clusterConf, clusterSubset);
236237
}

hbase-mapreduce/src/main/java/org/apache/hadoop/hbase/mapreduce/replication/VerifyReplication.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import org.apache.hadoop.hbase.client.Scan;
4242
import org.apache.hadoop.hbase.client.Table;
4343
import org.apache.hadoop.hbase.client.TableSnapshotScanner;
44+
import org.apache.hadoop.hbase.client.replication.ReplicationPeerConfigUtil;
4445
import org.apache.hadoop.hbase.filter.Filter;
4546
import org.apache.hadoop.hbase.filter.FilterList;
4647
import org.apache.hadoop.hbase.filter.PrefixFilter;
@@ -55,7 +56,6 @@
5556
import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
5657
import org.apache.hadoop.hbase.replication.ReplicationPeerStorage;
5758
import org.apache.hadoop.hbase.replication.ReplicationStorageFactory;
58-
import org.apache.hadoop.hbase.replication.ReplicationUtils;
5959
import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;
6060
import org.apache.hadoop.hbase.util.Bytes;
6161
import org.apache.hadoop.hbase.util.CommonFSUtils;
@@ -397,7 +397,7 @@ public boolean isAborted() {
397397
ReplicationStorageFactory.getReplicationPeerStorage(FileSystem.get(conf), localZKW, conf);
398398
ReplicationPeerConfig peerConfig = storage.getPeerConfig(peerId);
399399
return Pair.newPair(peerConfig,
400-
ReplicationUtils.getPeerClusterConfiguration(peerConfig, conf));
400+
ReplicationPeerConfigUtil.getPeerClusterConfiguration(conf, peerConfig));
401401
} catch (ReplicationException e) {
402402
throw new IOException("An error occurred while trying to connect to the remote peer cluster",
403403
e);

hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/replication/TestVerifyReplication.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ public class TestVerifyReplication extends TestReplicationBase {
8686
@Rule
8787
public TestName name = new TestName();
8888

89+
@Override
90+
protected String getClusterKey(HBaseTestingUtil util) throws Exception {
91+
// TODO: VerifyReplication does not support connection uri yet, so here we need to use cluster
92+
// key, as in this test we will pass the cluster key config in peer config directly to
93+
// VerifyReplication job.
94+
return util.getClusterKey();
95+
}
96+
8997
@Before
9098
public void setUp() throws Exception {
9199
cleanUp();

hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/replication/TestVerifyReplicationAdjunct.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,14 @@ public class TestVerifyReplicationAdjunct extends TestReplicationBase {
8181
@Rule
8282
public TestName name = new TestName();
8383

84+
@Override
85+
protected String getClusterKey(HBaseTestingUtil util) throws Exception {
86+
// TODO: VerifyReplication does not support connection uri yet, so here we need to use cluster
87+
// key, as in this test we will pass the cluster key config in peer config directly to
88+
// VerifyReplication job.
89+
return util.getClusterKey();
90+
}
91+
8492
@Before
8593
public void setUp() throws Exception {
8694
cleanUp();

0 commit comments

Comments
 (0)