-
Couldn't load subscription status.
- Fork 9.1k
HADOOP-18365. Update the remote address when a change is detected #4692
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4b610c8
590f5ba
168be14
1f1fdcf
cac2837
03cf96b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -323,7 +323,7 @@ public <T> ProtocolProxy<T> getProxy(Class<T> protocol, long clientVersion, | |
| Client.ConnectionId connId, Configuration conf, SocketFactory factory) | ||
| throws IOException { | ||
| return getProxy(protocol, clientVersion, connId.getAddress(), | ||
| connId.ticket, conf, factory, connId.getRpcTimeout(), | ||
| connId.getTicket(), conf, factory, connId.getRpcTimeout(), | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice but unrelated change. |
||
| connId.getRetryPolicy(), null, null); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ | |
|
|
||
| package org.apache.hadoop.ipc; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | ||
| import static org.junit.Assert.assertEquals; | ||
| import static org.junit.Assert.assertFalse; | ||
| import static org.junit.Assert.assertNotNull; | ||
|
|
@@ -93,6 +94,7 @@ | |
| import org.apache.hadoop.test.LambdaTestUtils; | ||
| import org.apache.hadoop.test.Whitebox; | ||
| import org.apache.hadoop.util.StringUtils; | ||
| import org.assertj.core.api.Condition; | ||
| import org.junit.Assert; | ||
| import org.junit.Assume; | ||
| import org.junit.Before; | ||
|
|
@@ -815,6 +817,81 @@ public Void call() throws IOException { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * The {@link ConnectionId#hashCode} has to be stable despite updates that occur as the the | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Double 'the'. |
||
| * address evolves over time. The {@link ConnectionId} is used as a primary key in maps, so | ||
| * its hashCode can't change. | ||
| * | ||
| * @throws IOException if there is a client or server failure | ||
| */ | ||
| @Test | ||
| public void testStableHashCode() throws IOException { | ||
| Server server = new TestServer(5, false); | ||
| try { | ||
| server.start(); | ||
|
|
||
| // Leave host unresolved to start. Use "localhost" as opposed | ||
| // to local IP from NetUtils.getConnectAddress(server) to force | ||
| // resolution later | ||
| InetSocketAddress unresolvedAddr = InetSocketAddress.createUnresolved( | ||
| "localhost", NetUtils.getConnectAddress(server).getPort()); | ||
|
|
||
| // Setup: Create a ConnectionID using an unresolved address, and get it's hashCode to serve | ||
| // as a point of comparison. | ||
| int rpcTimeout = MIN_SLEEP_TIME * 2; | ||
| final ConnectionId remoteId = getConnectionId(unresolvedAddr, rpcTimeout, conf); | ||
| int expected = remoteId.hashCode(); | ||
|
|
||
| // Start client | ||
| Client.setConnectTimeout(conf, 100); | ||
| Client client = new Client(LongWritable.class, conf); | ||
| try { | ||
| // Test: Call should re-resolve host and succeed | ||
| LongWritable param = new LongWritable(RANDOM.nextLong()); | ||
| client.call(RPC.RpcKind.RPC_BUILTIN, param, remoteId, | ||
| RPC.RPC_SERVICE_CLASS_DEFAULT, null); | ||
| int actual = remoteId.hashCode(); | ||
|
|
||
| // Verify: The hashCode should match, although the InetAddress is different since it has | ||
| // now been resolved | ||
| assertThat(remoteId.getAddress()).isNotEqualTo(unresolvedAddr); | ||
| assertThat(remoteId.getAddress().getHostName()).isEqualTo(unresolvedAddr.getHostName()); | ||
| assertThat(remoteId.hashCode()).isEqualTo(expected); | ||
|
|
||
| // Test: Call should succeed without having to re-resolve | ||
| InetSocketAddress expectedSocketAddress = remoteId.getAddress(); | ||
| param = new LongWritable(RANDOM.nextLong()); | ||
| client.call(RPC.RpcKind.RPC_BUILTIN, param, remoteId, | ||
| RPC.RPC_SERVICE_CLASS_DEFAULT, null); | ||
|
|
||
| // Verify: The same instance of the InetSocketAddress has been used to make the second | ||
| // call | ||
| assertThat(remoteId.getAddress()).isSameAs(expectedSocketAddress); | ||
|
|
||
| // Verify: The hashCode is protected against updates to the host name | ||
| String hostName = InetAddress.getLocalHost().getHostName(); | ||
| InetSocketAddress mismatchedHostName = NetUtils.createSocketAddr( | ||
| InetAddress.getLocalHost().getHostName(), | ||
| remoteId.getAddress().getPort()); | ||
| assertThatExceptionOfType(IllegalArgumentException.class) | ||
| .isThrownBy(() -> remoteId.setAddress(mismatchedHostName)) | ||
| .withMessageStartingWith("Hostname must match"); | ||
|
|
||
| // Verify: The hashCode is protected against updates to the port | ||
| InetSocketAddress mismatchedPort = NetUtils.createSocketAddr( | ||
| remoteId.getAddress().getHostName(), | ||
| remoteId.getAddress().getPort() + 1); | ||
| assertThatExceptionOfType(IllegalArgumentException.class) | ||
| .isThrownBy(() -> remoteId.setAddress(mismatchedPort)) | ||
| .withMessageStartingWith("Port must match"); | ||
| } finally { | ||
| client.stop(); | ||
| } | ||
| } finally { | ||
| server.stop(); | ||
| } | ||
| } | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice test. |
||
| @Test(timeout=60000) | ||
| public void testIpcFlakyHostResolution() throws IOException { | ||
| // start server | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The IllegalAddressException throw is unsettling but makes sense as long as the caller #updateAddress keeps making the currentAddr in the same way... I was going to say this method comment could be more explicit about what is happening in here and presumptions but I think the pointer to #updateAddress takes care of it....