HADOOP-9137. Support connection limiting in IPC server. Contributed by Kihwal Lee.
This commit is contained in:
parent
86358221fc
commit
8dc59cb9e0
@ -519,6 +519,8 @@ Release 2.7.0 - UNRELEASED
|
|||||||
HADOOP-11441. Hadoop-azure: Change few methods scope to public.
|
HADOOP-11441. Hadoop-azure: Change few methods scope to public.
|
||||||
(Shashank Khandelwal via cnauroth)
|
(Shashank Khandelwal via cnauroth)
|
||||||
|
|
||||||
|
HADOOP-9137. Support connection limiting in IPC server (kihwal)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
HADOOP-11323. WritableComparator#compare keeps reference to byte array.
|
HADOOP-11323. WritableComparator#compare keeps reference to byte array.
|
||||||
|
@ -227,6 +227,11 @@ public class CommonConfigurationKeysPublic {
|
|||||||
"ipc.server.tcpnodelay";
|
"ipc.server.tcpnodelay";
|
||||||
/** Default value for IPC_SERVER_TCPNODELAY_KEY */
|
/** Default value for IPC_SERVER_TCPNODELAY_KEY */
|
||||||
public static final boolean IPC_SERVER_TCPNODELAY_DEFAULT = true;
|
public static final boolean IPC_SERVER_TCPNODELAY_DEFAULT = true;
|
||||||
|
/** See <a href="{@docRoot}/../core-default.html">core-default.xml</a> */
|
||||||
|
public static final String IPC_SERVER_MAX_CONNECTIONS_KEY =
|
||||||
|
"ipc.server.max.connections";
|
||||||
|
/** Default value for IPC_SERVER_MAX_CONNECTIONS_KEY */
|
||||||
|
public static final int IPC_SERVER_MAX_CONNECTIONS_DEFAULT = 0;
|
||||||
|
|
||||||
/** See <a href="{@docRoot}/../core-default.html">core-default.xml</a> */
|
/** See <a href="{@docRoot}/../core-default.html">core-default.xml</a> */
|
||||||
public static final String HADOOP_RPC_SOCKET_FACTORY_CLASS_DEFAULT_KEY =
|
public static final String HADOOP_RPC_SOCKET_FACTORY_CLASS_DEFAULT_KEY =
|
||||||
|
@ -749,6 +749,13 @@ void doAccept(SelectionKey key) throws InterruptedException, IOException, OutOf
|
|||||||
|
|
||||||
Reader reader = getReader();
|
Reader reader = getReader();
|
||||||
Connection c = connectionManager.register(channel);
|
Connection c = connectionManager.register(channel);
|
||||||
|
// If the connectionManager can't take it, close the connection.
|
||||||
|
if (c == null) {
|
||||||
|
if (channel.isOpen()) {
|
||||||
|
IOUtils.cleanup(null, channel);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
key.attach(c); // so closeCurrentConnection can get the object
|
key.attach(c); // so closeCurrentConnection can get the object
|
||||||
reader.addConnection(c);
|
reader.addConnection(c);
|
||||||
}
|
}
|
||||||
@ -2731,6 +2738,7 @@ private class ConnectionManager {
|
|||||||
final private int idleScanInterval;
|
final private int idleScanInterval;
|
||||||
final private int maxIdleTime;
|
final private int maxIdleTime;
|
||||||
final private int maxIdleToClose;
|
final private int maxIdleToClose;
|
||||||
|
final private int maxConnections;
|
||||||
|
|
||||||
ConnectionManager() {
|
ConnectionManager() {
|
||||||
this.idleScanTimer = new Timer(
|
this.idleScanTimer = new Timer(
|
||||||
@ -2747,6 +2755,9 @@ private class ConnectionManager {
|
|||||||
this.maxIdleToClose = conf.getInt(
|
this.maxIdleToClose = conf.getInt(
|
||||||
CommonConfigurationKeysPublic.IPC_CLIENT_KILL_MAX_KEY,
|
CommonConfigurationKeysPublic.IPC_CLIENT_KILL_MAX_KEY,
|
||||||
CommonConfigurationKeysPublic.IPC_CLIENT_KILL_MAX_DEFAULT);
|
CommonConfigurationKeysPublic.IPC_CLIENT_KILL_MAX_DEFAULT);
|
||||||
|
this.maxConnections = conf.getInt(
|
||||||
|
CommonConfigurationKeysPublic.IPC_SERVER_MAX_CONNECTIONS_KEY,
|
||||||
|
CommonConfigurationKeysPublic.IPC_SERVER_MAX_CONNECTIONS_DEFAULT);
|
||||||
// create a set with concurrency -and- a thread-safe iterator, add 2
|
// create a set with concurrency -and- a thread-safe iterator, add 2
|
||||||
// for listener and idle closer threads
|
// for listener and idle closer threads
|
||||||
this.connections = Collections.newSetFromMap(
|
this.connections = Collections.newSetFromMap(
|
||||||
@ -2774,11 +2785,19 @@ int size() {
|
|||||||
return count.get();
|
return count.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean isFull() {
|
||||||
|
// The check is disabled when maxConnections <= 0.
|
||||||
|
return ((maxConnections > 0) && (size() >= maxConnections));
|
||||||
|
}
|
||||||
|
|
||||||
Connection[] toArray() {
|
Connection[] toArray() {
|
||||||
return connections.toArray(new Connection[0]);
|
return connections.toArray(new Connection[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection register(SocketChannel channel) {
|
Connection register(SocketChannel channel) {
|
||||||
|
if (isFull()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Connection connection = new Connection(channel, Time.now());
|
Connection connection = new Connection(channel, Time.now());
|
||||||
add(connection);
|
add(connection);
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
|
@ -1677,4 +1677,15 @@ for ldap providers in the same way as above does.
|
|||||||
</description>
|
</description>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property>
|
||||||
|
<name>ipc.server.max.connections</name>
|
||||||
|
<value>0</value>
|
||||||
|
<description>The maximum number of concurrent connections a server is allowed
|
||||||
|
to accept. If this limit is exceeded, incoming connections will first fill
|
||||||
|
the listen queue and then may go to an OS-specific listen overflow queue.
|
||||||
|
The client may fail or timeout, but the server can avoid running out of file
|
||||||
|
descriptors using this feature. 0 means no limit.
|
||||||
|
</description>
|
||||||
|
</property>
|
||||||
|
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -1184,6 +1184,57 @@ public void run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMaxConnections() throws Exception {
|
||||||
|
conf.setInt("ipc.server.max.connections", 5);
|
||||||
|
Server server = null;
|
||||||
|
Thread connectors[] = new Thread[10];
|
||||||
|
|
||||||
|
try {
|
||||||
|
server = new TestServer(3, false);
|
||||||
|
final InetSocketAddress addr = NetUtils.getConnectAddress(server);
|
||||||
|
server.start();
|
||||||
|
assertEquals(0, server.getNumOpenConnections());
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
connectors[i] = new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Socket sock = null;
|
||||||
|
try {
|
||||||
|
sock = NetUtils.getDefaultSocketFactory(conf).createSocket();
|
||||||
|
NetUtils.connect(sock, addr, 3000);
|
||||||
|
try {
|
||||||
|
Thread.sleep(4000);
|
||||||
|
} catch (InterruptedException ie) { }
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
} finally {
|
||||||
|
if (sock != null) {
|
||||||
|
try {
|
||||||
|
sock.close();
|
||||||
|
} catch (IOException ioe) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
connectors[i].start();
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
// server should only accept up to 5 connections
|
||||||
|
assertEquals(5, server.getNumOpenConnections());
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
connectors[i].join();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (server != null) {
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
conf.setInt("ipc.server.max.connections", 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void assertRetriesOnSocketTimeouts(Configuration conf,
|
private void assertRetriesOnSocketTimeouts(Configuration conf,
|
||||||
int maxTimeoutRetries) throws IOException {
|
int maxTimeoutRetries) throws IOException {
|
||||||
SocketFactory mockFactory = Mockito.mock(SocketFactory.class);
|
SocketFactory mockFactory = Mockito.mock(SocketFactory.class);
|
||||||
|
Loading…
Reference in New Issue
Block a user