[ 
https://issues.apache.org/jira/browse/HADOOP-18365?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17581419#comment-17581419
 ] 

ASF GitHub Bot commented on HADOOP-18365:
-----------------------------------------

saintstack commented on code in PR #4692:
URL: https://github.com/apache/hadoop/pull/4692#discussion_r949336930


##########
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java:
##########
@@ -1753,7 +1756,28 @@ public ConnectionId(InetSocketAddress address, Class<?> 
protocol,
     InetSocketAddress getAddress() {
       return address;
     }
-    
+
+    /**
+     * This is used to update the remote address when an address change is 
detected.  This method
+     * ensures that the {@link #hashCode()} won't change.
+     *
+     * @param address the updated address
+     * @throws IllegalArgumentException if the hostname or port doesn't match
+     * @see Connection#updateAddress()

Review Comment:
   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....



##########
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestIPC.java:
##########
@@ -815,6 +817,81 @@ public Void call() throws IOException {
     }
   }
 
+  /**
+   * The {@link ConnectionId#hashCode} has to be stable despite updates that 
occur as the 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();
+    }
+  }
+

Review Comment:
   Nice test.



##########
hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/WritableRpcEngine.java:
##########
@@ -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(),

Review Comment:
   Nice but unrelated change.



##########
hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/TestIPC.java:
##########
@@ -815,6 +817,81 @@ public Void call() throws IOException {
     }
   }
 
+  /**
+   * The {@link ConnectionId#hashCode} has to be stable despite updates that 
occur as the the

Review Comment:
   Double 'the'.





> Updated addresses are still accessed using the old IP address
> -------------------------------------------------------------
>
>                 Key: HADOOP-18365
>                 URL: https://issues.apache.org/jira/browse/HADOOP-18365
>             Project: Hadoop Common
>          Issue Type: Improvement
>          Components: common
>         Environment: Demonstrated in a Kubernetes environment running Java 11.
>            Reporter: Steve Vaughan
>            Assignee: Steve Vaughan
>            Priority: Major
>              Labels: pull-request-available
>          Time Spent: 0.5h
>  Remaining Estimate: 0h
>
> When the IPC Client recognizes that an IP address has changed, it updates the 
> server field and logs a message:
> Address change detected. Old: 
> journalnode-1.journalnode.hdfs.svc.cluster.local/10.1.0.178:8485 New: 
> journalnode-1.journalnode.hdfs.svc.cluster.local/10.1.0.182:8485
> Although the change is detected, the client will continue to connect to the 
> old IP address, resulting in repeated log messages.  This is seen in managed 
> environments when JournalNode syncing is enabled and a JournalNode is 
> restarted, with the remaining nodes in the set repeatedly logging this 
> message when syncing to the restarted JournalNode.
> The source of the problem is that the remoteId.address is not updated.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to