From e9b9897abae5cde0d8255cb906039c587ee2be90 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Tue, 8 Dec 2015 14:47:10 +0000 Subject: [PATCH] Add timeout (default 1sec) to hostname lookup User can set spring.util.timeout.sec (or env var equivalent with CAP_CASE). Fixes gh-55 --- .../springframework/cloud/util/InetUtils.java | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/spring-cloud-commons/src/main/java/org/springframework/cloud/util/InetUtils.java b/spring-cloud-commons/src/main/java/org/springframework/cloud/util/InetUtils.java index 93ef8b09..5de543b8 100644 --- a/spring-cloud-commons/src/main/java/org/springframework/cloud/util/InetUtils.java +++ b/spring-cloud-commons/src/main/java/org/springframework/cloud/util/InetUtils.java @@ -7,6 +7,13 @@ import java.net.NetworkInterface; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.util.Enumeration; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.springframework.util.SystemPropertyUtils; import lombok.Data; import lombok.SneakyThrows; @@ -18,9 +25,11 @@ import lombok.extern.apachecommons.CommonsLog; @CommonsLog public class InetUtils { + private static ExecutorService executor = Executors.newSingleThreadExecutor(); + /** - * Find the first non-loopback host info. - * If there were errors return a hostinfo with 'localhost' and '127.0.0.1' for hostname and ipAddress respectively. + * Find the first non-loopback host info. If there were errors return a hostinfo with + * 'localhost' and '127.0.0.1' for hostname and ipAddress respectively. */ public static HostInfo getFirstNonLoopbackHostInfo() { InetAddress address = getFirstNonLoopbackAddress(); @@ -39,14 +48,18 @@ public class InetUtils { @SneakyThrows public static InetAddress getFirstNonLoopbackAddress() { try { - for (Enumeration enumNic = NetworkInterface.getNetworkInterfaces(); - enumNic.hasMoreElements(); ) { + for (Enumeration enumNic = NetworkInterface + .getNetworkInterfaces(); enumNic.hasMoreElements();) { NetworkInterface ifc = enumNic.nextElement(); if (ifc.isUp()) { - for (Enumeration enumAddr = ifc.getInetAddresses(); - enumAddr.hasMoreElements(); ) { + log.debug("Testing interface: " + ifc.getDisplayName()); + for (Enumeration enumAddr = ifc + .getInetAddresses(); enumAddr.hasMoreElements();) { InetAddress address = enumAddr.nextElement(); - if (address instanceof Inet4Address && !address.isLoopbackAddress()) { + if (address instanceof Inet4Address + && !address.isLoopbackAddress()) { + log.debug("Found non-loopback interface: " + + ifc.getDisplayName()); return address; } } @@ -59,16 +72,34 @@ public class InetUtils { try { return InetAddress.getLocalHost(); - } catch (UnknownHostException e) { + } + catch (UnknownHostException e) { log.warn("Unable to retrieve localhost"); } return null; } - public static HostInfo convert(InetAddress address) { + public static HostInfo convert(final InetAddress address) { HostInfo hostInfo = new HostInfo(); - hostInfo.setHostname(address.getHostName()); + Future result = executor.submit(new Callable() { + @Override + public String call() throws Exception { + return address.getHostName(); + } + }); + + String hostname; + try { + SystemPropertyUtils.resolvePlaceholders( + "${spring.util.timeout.sec:${SPRING_UTIL_TIMEOUT_SEC:1}"); + hostname = result.get(1, TimeUnit.SECONDS); + } + catch (Exception e) { + log.info("Cannot determine local hostname"); + hostname = "localhost"; + } + hostInfo.setHostname(hostname); hostInfo.setIpAddress(address.getHostAddress()); return hostInfo; } @@ -78,6 +109,7 @@ public class InetUtils { public boolean override; private String ipAddress; private String hostname; + public int getIpAddressAsInt() { InetAddress inetAddress = null; try {