diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java index 20f24cae643..4f106d87391 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/ipc/RpcServer.java @@ -196,7 +196,7 @@ public class RpcServer implements RpcServerInterface { static final ThreadLocal MONITORED_RPC = new ThreadLocal(); - protected final InetSocketAddress isa; + protected final InetSocketAddress bindAddress; protected int port; // port we listen on private int readThreads; // number of read threads protected int maxIdleTime; // the maximum idle time after @@ -521,8 +521,8 @@ public class RpcServer implements RpcServerInterface { acceptChannel = ServerSocketChannel.open(); acceptChannel.configureBlocking(false); - // Bind the server socket to the local host and port - bind(acceptChannel.socket(), isa, backlogLength); + // Bind the server socket to the binding addrees (can be different from the default interface) + bind(acceptChannel.socket(), bindAddress, backlogLength); port = acceptChannel.socket().getLocalPort(); //Could be an ephemeral port // create a selector; selector= Selector.open(); @@ -530,7 +530,8 @@ public class RpcServer implements RpcServerInterface { readers = new Reader[readThreads]; readPool = Executors.newFixedThreadPool(readThreads, new ThreadFactoryBuilder().setNameFormat( - "RpcServer.reader=%d,port=" + port).setDaemon(true).build()); + "RpcServer.reader=%d,bindAddress=" + bindAddress.getHostName() + + ",port=" + port).setDaemon(true).build()); for (int i = 0; i < readThreads; ++i) { Reader reader = new Reader(); readers[i] = reader; @@ -1869,17 +1870,18 @@ public class RpcServer implements RpcServerInterface { * instance else pass null for no authentication check. * @param name Used keying this rpc servers' metrics and for naming the Listener thread. * @param services A list of services. - * @param isa Where to listen + * @param bindAddres Where to listen * @throws IOException */ public RpcServer(final Server server, final String name, final List services, - final InetSocketAddress isa, Configuration conf, + final InetSocketAddress bindAddress, Configuration conf, RpcScheduler scheduler) - throws IOException { + throws IOException { + this.server = server; this.services = services; - this.isa = isa; + this.bindAddress = bindAddress; this.conf = conf; this.socketSendBufferSize = 0; this.maxQueueSize = diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java index 8aef52bcabb..3f55ab512b4 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/RSRpcServices.java @@ -779,6 +779,8 @@ public class RSRpcServices implements HBaseRPCErrorHandler, HConstants.DEFAULT_REGIONSERVER_PORT); // Creation of a HSA will force a resolve. InetSocketAddress initialIsa = new InetSocketAddress(hostname, port); + InetSocketAddress bindAddress = new InetSocketAddress( + rs.conf.get("hbase.regionserver.ipc.address", hostname), port); if (initialIsa.getAddress() == null) { throw new IllegalArgumentException("Failed resolve of " + initialIsa); } @@ -787,7 +789,7 @@ public class RSRpcServices implements HBaseRPCErrorHandler, // Set how many times to retry talking to another server over HConnection. ConnectionUtils.setServerSideHConnectionRetriesConfig(rs.conf, name, LOG); rpcServer = new RpcServer(rs, name, getServices(), - initialIsa, // BindAddress is IP we got for this server. + bindAddress, // use final bindAddress for this server. rs.conf, rpcSchedulerFactory.create(rs.conf, this, rs)); @@ -798,17 +800,16 @@ public class RSRpcServices implements HBaseRPCErrorHandler, HConstants.HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE_KEY, HConstants.DEFAULT_HBASE_CLIENT_SCANNER_MAX_RESULT_SIZE); - // Set our address. - isa = rpcServer.getListenerAddress(); + // Set our address, however we need the final port that was given to rpcServer + isa = new InetSocketAddress(initialIsa.getHostName(), rpcServer.getListenerAddress().getPort()); rpcServer.setErrorHandler(this); rs.setName(name); } public static String getHostname(Configuration conf) throws UnknownHostException { - return conf.get("hbase.regionserver.ipc.address", - Strings.domainNamePointerToHostName(DNS.getDefaultHost( + return Strings.domainNamePointerToHostName(DNS.getDefaultHost( conf.get("hbase.regionserver.dns.interface", "default"), - conf.get("hbase.regionserver.dns.nameserver", "default")))); + conf.get("hbase.regionserver.dns.nameserver", "default"))); } RegionScanner getScanner(long scannerId) { diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHBaseTestingUtility.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHBaseTestingUtility.java index ecd748090b7..856cc9e87a4 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHBaseTestingUtility.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/TestHBaseTestingUtility.java @@ -124,6 +124,18 @@ public class TestHBaseTestingUtility { } } + @Test + public void testMiniClusterBindToWildcard() throws Exception { + HBaseTestingUtility hbt = new HBaseTestingUtility(); + hbt.getConfiguration().set("hbase.regionserver.ipc.address", "0.0.0.0"); + MiniHBaseCluster cluster = hbt.startMiniCluster(); + try { + assertEquals(1, cluster.getLiveRegionServerThreads().size()); + } finally { + hbt.shutdownMiniCluster(); + } + } + /** * Test that we can start and stop multiple time a cluster * with the same HBaseTestingUtility.