HDFS-12865. RequestHedgingProxyProvider should handle case when none of the proxies are available. Contributed by Mukul Kumar Singh.

This commit is contained in:
Arpit Agarwal 2018-02-24 14:25:56 -08:00
parent 57095b68dc
commit c5602ea124
2 changed files with 51 additions and 0 deletions

View File

@ -17,6 +17,7 @@
*/
package org.apache.hadoop.hdfs.server.namenode.ha;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@ -87,6 +88,11 @@ public class RequestHedgingProxyProvider<T> extends
// Optimization : if only 2 proxies are configured and one had failed
// over, then we dont need to create a threadpool etc.
targetProxies.remove(toIgnore);
if (targetProxies.size() == 0) {
LOG.trace("No valid proxies left");
throw new RemoteException(IOException.class.getName(),
"No valid proxies left. All NameNode proxies have failed over.");
}
if (targetProxies.size() == 1) {
ProxyInfo<T> proxyInfo = targetProxies.values().iterator().next();
try {

View File

@ -28,6 +28,7 @@ import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.client.HdfsClientConfigKeys;
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
@ -289,6 +290,50 @@ public class TestRequestHedgingProxyProvider {
}
}
@Test
public void testSingleProxyFailover() throws Exception {
String singleNS = "mycluster-" + Time.monotonicNow();
URI singleNNUri = new URI("hdfs://" + singleNS);
Configuration singleConf = new Configuration();
singleConf.set(HdfsClientConfigKeys.DFS_NAMESERVICES, singleNS);
singleConf.set(HdfsClientConfigKeys.
DFS_HA_NAMENODES_KEY_PREFIX + "." + singleNS, "nn1");
singleConf.set(HdfsClientConfigKeys.
DFS_NAMENODE_RPC_ADDRESS_KEY + "." + singleNS + ".nn1",
RandomStringUtils.randomAlphabetic(8) + ".foo.bar:9820");
ClientProtocol active = Mockito.mock(ClientProtocol.class);
Mockito
.when(active.getBlockLocations(Matchers.anyString(),
Matchers.anyLong(), Matchers.anyLong()))
.thenThrow(new RemoteException("java.io.FileNotFoundException",
"File does not exist!"));
RequestHedgingProxyProvider<ClientProtocol> provider =
new RequestHedgingProxyProvider<>(singleConf, singleNNUri,
ClientProtocol.class, createFactory(active));
try {
provider.getProxy().proxy.getBlockLocations("/tmp/test.file", 0L, 20L);
Assert.fail("Should fail since the active namenode throws"
+ " FileNotFoundException!");
} catch (RemoteException ex) {
Exception rEx = ex.unwrapRemoteException();
Assert.assertTrue(rEx instanceof FileNotFoundException);
}
//Perform failover now, there will be no active proxies now
provider.performFailover(active);
try {
provider.getProxy().proxy.getBlockLocations("/tmp/test.file", 0L, 20L);
Assert.fail("Should fail since the active namenode throws"
+ " FileNotFoundException!");
} catch (RemoteException ex) {
Exception rEx = ex.unwrapRemoteException();
Assert.assertTrue(rEx instanceof IOException);
Assert.assertTrue(rEx.getMessage().equals("No valid proxies left."
+ " All NameNode proxies have failed over."));
}
}
@Test
public void testPerformFailoverWith3Proxies() throws Exception {
conf.set(HdfsClientConfigKeys.DFS_HA_NAMENODES_KEY_PREFIX + "." + ns,