Spring Boot与Eureka环境下java.net.UnknownHostException报错修复
解决非Spring Boot客户端通过RestTemplate调用Eureka注册服务时的UnknownHostException问题
看起来你遇到的核心问题是:你的客户端不是Spring Boot应用,因此Spring Cloud的自动配置机制没有生效——即便给RestTemplate加了@LoadBalanced注解,它也不会自动具备服务名解析能力。下面是具体的排查和解决步骤:
1. 确认依赖是否齐全
首先要确保项目引入了服务发现和负载均衡的必要Spring Cloud依赖:
- 若使用Spring Cloud 2020.0.0(Ilford)及以后版本,推荐引入
spring-cloud-starter-loadbalancer(替代旧版Ribbon) - 必须引入
spring-cloud-starter-netflix-eureka-client来连接Eureka Server
Maven依赖示例:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
2. 手动配置具备负载均衡能力的RestTemplate
非Spring Boot应用不会自动加载LoadBalancerAutoConfiguration,所以需要手动给RestTemplate添加负载均衡拦截器,让它能通过服务名从Eureka获取实例地址:
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.web.client.RestTemplate; import java.util.Collections; @Configuration public class RestTemplateConfig { @Bean public LoadBalancerClient loadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) { return new org.springframework.cloud.client.loadbalancer.DefaultLoadBalancerClient(loadBalancerClientFactory); } @Bean public LoadBalancerClientFactory loadBalancerClientFactory() { LoadBalancerClientFactory factory = new LoadBalancerClientFactory(); // 配置默认轮询负载均衡策略(可选) factory.setConfigurations(Collections.singletonList(new org.springframework.cloud.loadbalancer.core.DefaultLoadBalancerConfiguration())); return factory; } @Bean @Primary // 若存在多个RestTemplate实例,标记此为默认 public RestTemplate loadBalancedRestTemplate(LoadBalancerClient loadBalancerClient) { RestTemplate restTemplate = new RestTemplate(); // 添加负载均衡拦截器,让RestTemplate能解析服务名 restTemplate.setInterceptors(Collections.singletonList(new LoadBalancerInterceptor(loadBalancerClient))); return restTemplate; } }
3. 正确配置Eureka客户端
确保配置类启用服务发现,并配置Eureka Server地址:
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.Configuration; @Configuration @EnableDiscoveryClient // 启用通用服务发现(替代@EnableEurekaClient) public class EurekaConfig { }
然后在application.properties中添加Eureka配置:
# Eureka Server地址 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ # 若客户端无需注册到Eureka,仅需发现服务,设置为false eureka.client.register-with-eureka=false # 定期拉取服务注册表 eureka.client.fetch-registry=true
4. 验证服务发现是否正常
在发起请求前,可先验证客户端是否能从Eureka获取目标服务:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Component; @Component public class ServiceChecker { @Autowired private DiscoveryClient discoveryClient; public void verifyServiceExists() { boolean serviceExists = discoveryClient.getServices().contains("documents-microservice"); if (serviceExists) { System.out.println("目标服务已在Eureka中注册"); // 打印具体实例地址 discoveryClient.getInstances("documents-microservice").forEach(instance -> { System.out.println("实例地址:" + instance.getUri()); }); } else { System.err.println("未从Eureka获取到documents-microservice服务"); } } }
5. 确保Spring上下文正确初始化
非Spring Boot应用需要手动初始化Spring上下文,确保所有配置类被扫描到:
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.http.HttpEntity; import org.springframework.web.client.RestTemplate; public class ClientApplication { public static void main(String[] args) { // 加载配置类,初始化Spring上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( EurekaConfig.class, RestTemplateConfig.class, ServiceChecker.class ); // 先验证服务可用性 ServiceChecker checker = context.getBean(ServiceChecker.class); checker.verifyServiceExists(); // 使用具备负载均衡的RestTemplate发起请求 RestTemplate restTemplate = context.getBean(RestTemplate.class); HttpEntity<String> entity = new HttpEntity<>("请求体内容"); // 替换为你的请求实体 ResponseEntity<String> response = restTemplate.exchange( "http://documents-microservice/document-name", HttpMethod.POST, entity, String.class ); } }
关键总结
非Spring Boot应用无法享受Spring Boot的自动配置红利,必须手动完成以下操作:
- 引入必要的Spring Cloud依赖
- 配置LoadBalanced相关Bean,给RestTemplate添加负载均衡拦截器
- 启用服务发现并正确配置Eureka地址
这样RestTemplate就能正常解析服务名,从Eureka获取实例地址发起请求了。
内容的提问来源于stack exchange,提问作者Travelling Salesman
相关产品推荐
相关产品推荐

