[ https://issues.apache.org/jira/browse/ZOOKEEPER-2691?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15872523#comment-15872523 ]
ASF GitHub Bot commented on ZOOKEEPER-2691: ------------------------------------------- Github user eribeiro commented on a diff in the pull request: https://github.com/apache/zookeeper/pull/173#discussion_r101843694 --- Diff: src/java/main/org/apache/zookeeper/server/quorum/QuorumPeer.java --- @@ -128,24 +136,32 @@ private QuorumServer(long id, InetSocketAddress addr, this.addr = addr; this.electionAddr = electionAddr; this.type = type; + String checkIPReachableValue = System.getProperty("zookeeper.checkIPTimeout"); + if(checkIPReachableValue != null){ + this.checkIPReachableTO = Integer.parseInt(checkIPReachableValue); + } } public QuorumServer(long id, String hostname, Integer port, Integer electionPort, LearnerType type) { - this.id = id; - this.hostname=hostname; - if (port!=null){ + this.id = id; + this.hostname=hostname; + if (port!=null){ this.port=port; - } - if (electionPort!=null){ + } + if (electionPort!=null){ this.electionPort=electionPort; - } - if (type!=null){ + } + if (type!=null){ this.type = type; - } - this.recreateSocketAddresses(); } + String checkIPReachableValue = System.getProperty("zookeeper.checkIPTimeout"); + if(checkIPReachableValue != null){ --- End diff -- nit: space between `if` and `(` > recreateSocketAddresses may recreate the unreachable IP address > --------------------------------------------------------------- > > Key: ZOOKEEPER-2691 > URL: https://issues.apache.org/jira/browse/ZOOKEEPER-2691 > Project: ZooKeeper > Issue Type: Bug > Affects Versions: 3.4.8 > Environment: Centos6.5 > Java8 > ZooKeeper3.4.8 > Reporter: JiangJiafu > Priority: Minor > > The QuorumPeer$QuorumServer.recreateSocketAddress() is used to resolved the > hostname to a new IP address(InetAddress) when any exception happens to the > socket. It will be very useful when a hostname can be resolved to more than > one IP address. > But the problem is Java API InetAddress.getByName(String hostname) will > always return the first IP address when the hostname can be resolved to more > than one IP address, and the first IP address may be unreachable forever. For > example, if a machine has two network interfaces: eth0, eth1, say eth0 has > ip1, eth1 has ip2, the relationship between hostname and the IP addresses is > set in /etc/hosts. When I "close" the eth0 by command "ifdown eth0", the > InetAddress.getByName(String hostname) will still return ip1, which is > unreachable forever. > So I think it will be better to check the IP address by > InetAddress.isReachable(long) and choose the reachable IP address. > I have modified the ZooKeeper source code, and test the new code in my own > environment, and it can work very well when I turn down some network > interfaces using "ifdown" command. > The original code is: > {code:title=QuorumPeer.java|borderStyle=solid} > public void recreateSocketAddresses() { > InetAddress address = null; > try { > address = InetAddress.getByName(this.hostname); > LOG.info("Resolved hostname: {} to address: {}", > this.hostname, address); > this.addr = new InetSocketAddress(address, this.port); > if (this.electionPort > 0){ > this.electionAddr = new InetSocketAddress(address, > this.electionPort); > } > } catch (UnknownHostException ex) { > LOG.warn("Failed to resolve address: {}", this.hostname, ex); > // Have we succeeded in the past? > if (this.addr != null) { > // Yes, previously the lookup succeeded. Leave things as > they are > return; > } > // The hostname has never resolved. Create our > InetSocketAddress(es) as unresolved > this.addr = InetSocketAddress.createUnresolved(this.hostname, > this.port); > if (this.electionPort > 0){ > this.electionAddr = > InetSocketAddress.createUnresolved(this.hostname, > > this.electionPort); > } > } > } > {code} > After my modification: > {code:title=QuorumPeer.java|borderStyle=solid} > public void recreateSocketAddresses() { > InetAddress address = null; > try { > address = getReachableAddress(this.hostname); > LOG.info("Resolved hostname: {} to address: {}", > this.hostname, address); > this.addr = new InetSocketAddress(address, this.port); > if (this.electionPort > 0){ > this.electionAddr = new InetSocketAddress(address, > this.electionPort); > } > } catch (UnknownHostException ex) { > LOG.warn("Failed to resolve address: {}", this.hostname, ex); > // Have we succeeded in the past? > if (this.addr != null) { > // Yes, previously the lookup succeeded. Leave things as > they are > return; > } > // The hostname has never resolved. Create our > InetSocketAddress(es) as unresolved > this.addr = InetSocketAddress.createUnresolved(this.hostname, > this.port); > if (this.electionPort > 0){ > this.electionAddr = > InetSocketAddress.createUnresolved(this.hostname, > > this.electionPort); > } > } > } > public InetAddress getReachableAddress(String hostname) throws > UnknownHostException { > InetAddress[] addresses = InetAddress.getAllByName(hostname); > for (InetAddress a : addresses) { > try { > if (a.isReachable(5000)) { > return a; > } > } catch (IOException e) { > LOG.warn("IP address {} is unreachable", a); > } > } > // All the IP address is unreachable, just return the first one. > return addresses[0]; > } > {code} -- This message was sent by Atlassian JIRA (v6.3.15#6346)