How to fix services registering as localhost on Eureka
If you’ve been using Spring cloud to develop microservices, chances are, you might have used Eureka.
Eureka is a service registry, which means microservices use it to register themselves. This allows other applications and services to look up the address of a microservice through the registry. The benefit of that is that you no longer have to rely on hardcoded hostnames and ports, because these could change.
Eureka is often used with either Feign or Ribbon, which will resolve the hostname for you, and provide client-side loadbalancing if there are multiple instances of the same microservices.
Nowadays you see less people using Eureka, since there are other alternatives on the market such as container orchestration (eg. Kubernetes).
One issue with Eureka is that services sometimes accidentally register themselves as localhost. This causes issues, because applications on other servers will now try to connect to the microservice on localhost, rather than the proper location.
When searching on the internet for solutions, people often tell you to use IP addresses in stead. However, this is rather just a workaround, and not a solution to the problem.
If you take a look at the code, you’ll see that the way Spring relies on a class called
InetUtils to resolve the hostname.
The way this class works is the following. First of all, it retrieves a list of all network interfaces.
After that, it will loop over all network interfaces, and find the first IPv4 network address of those interfaces. (See
Once it retrieve that address, it will register that application with the hostname of that address (See
Before we take a look at why this might fail, we first have to enable debug logging for the
InetUtilsclass. This can be done by adding the following application property:
logging: level: org.springframework.cloud.commons.util.InetUtils: trace
Now, let’s dive into the reasons why the lookup might fail.
One possibility why you get the wrong hostname is because it picked the wrong network interface or address. To find out which network interface is used, you can check the logs for the following messages:
Testing interface: Software Loopback Interface 1 Testing interface: vmxnet3 Ethernet Adapter Found non-loopback interface: vmxnet3 Ethernet Adapter
As you can see, in this example, the “vmxnet3 Ethernet Adapter” was picked. If this isn’t the proper network interface, you can ignore it by configuring the
spring: cloud: inetutils: ignored-interfaces: # You can use wildcards as well - vmxnet3*
Make sure not to ignore all network interfaces, as this will cause issues as well.
When an error occurs, the
InetUtils class will try to retrieve the local host address by calling
InetAddress.getLocalHost(). If that fails, it will rely on a fallback property called
To see whether this happens, look either for a message “Cannot get first non-loopback address”, followed by an exception, or for the “Unable to retrieve localhost” message.
If no network interface or address could be found, the same will happen as when an error occurs.
To verify whether this is the case, there should be no message within the logs starting with “Testing interface” and the “Found non-loopback interface” logging message should also be absent.
Be aware, there are certain properties that limit which network interfaces or IP addresses are accepted.
For example, we already mentioned that
spring.cloud.inetutils.ignored-interfaces can be used to ignore certain network interfaces.
In addition, you can also limit the addresses by configuring the preferred ranges:
spring: cloud: inetutils: preferred-networks: - 192.168
That means that if either of these are wrongly configured, no address might be found.
The most common issue that causes
localhost to be used is when it takes too long to resolve the hostname. To verify whether this is the case, you have to look for the following message within the logs:
Cannot determine local hostname
As you can see in
InetUtils.convertAddress(), there is a time limitation. By default, this is 1 second.
This means that if it takes more than one second to resolve the hostname, the code will fall back on
Beware, this fallback is hardcoded and changing the
spring.cloud.inetutils.default-hostname property will have no effect.
Luckily, we can increase the amount of seconds it takes before the fallback is being used. For example:
spring: cloud: inetutils: timeout-seconds: 10
As you can see, microservices don’t just register themselves randomly as localhost. There’s always a clear cause, and enabling trace logging or debugging the
InetUtils class will be helpful to find out why.
There are also several properties that affect how
InetUtils behaves, which I listed before. For more information about these properties, you can always check the Spring Cloud Commons Appendix A. When doing so, make sure to look for properties starting with