Spring Eureka无法识别服务实例,跨服务调用失败求助
问题背景
搭建了包含chat-ws、users-ws和discovery-service的微服务集群,尝试从chat-ws向users-ws发起内部HTTP调用时遇到以下问题:
- 调用
discoveryClient.getInstancesById("USERS-WS")或"users-ws"时,实例列表始终为空 - WebClient调用返回DNS解析失败错误,提示无法解析
users-ws - Eureka控制台显示
USERS-WS和CHAT-WS已正常注册,所有服务均添加了对应注解(@EnableDiscoveryClient、@EnableEurekaServer)
相关代码与错误日志
chat-ws中调用users-ws的代码:
public void getUsersData(List<String> userIds){ List<InstanceInfo>instance = discoveryClient.getInstancesById("USERS-WS"); log.info("instances --> " + instance); String url = "http://users-ws/api/user/usersdata"; String json = toJson(userIds); log.info("json --> " + json); Mono<String> response = webClient .post() .uri(url) .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(json)) .retrieve() .bodyToMono(String.class); response.subscribe( responseBody ->{ log.info("response body --> " + responseBody); }, error -> { log.warn("error --> " + error); } ); }
WebClient返回的错误日志:
[id: 0xd2582735] RECEIVED: UDP [55785: /192.168.2.1:53], DatagramDnsResponse(from: /192.168.2.1:53, to: /[0:0:0:0:0:0:0:0]:61795, id: 55785, QUERY(0), NXDomain(3), RD RA) [ctor-http-nio-1] io.netty.resolver.dns.DnsQueryContext : [id: 0xd2582735] WRITE: UDP, [47691: /192.168.2.1:53], DefaultDnsQuestion(users-ws. IN CNAME) [ctor-http-nio-1] io.netty.resolver.dns.DnsNameResolver : [id: 0xd2582735] RECEIVED: UDP [47691: /192.168.2.1:53], DatagramDnsResponse(from: /192.168.2.1:53, to: /[0:0:0:0:0:0:0:0]:61795, id: 47691, QUERY(0), NXDomain(3), RD RA) error --> org.springframework.web.reactive.function.client.WebClientRequestException: Failed to resolve 'users-ws' [A(1)] after 2 queries
各服务配置文件:
discovery-service配置
server.port=8086 spring.application.name=discoveryservice eureka.instance.hostname=localhost eureka.client.register-with-eureka=false eureka.client.fetch-registry=false logging.level.com.netflix.discovery=DEBUG
chat-service配置
server.port=${PORT:0} spring.application.name=chat-ws eureka.client.service-url.defaultZone=http://localhost:8086/eureka eureka.instance.instance-id=${spring.application.name}:${spring.application.instance_id:${random.value}} eureka.client.fetch-registry=true eureka.client.register-with-eureka=true eureka.client.enabled=true gateway.ip=192.168.2.184 logging.level.root=DEBUG
user-service配置
server.port=${PORT:0} spring.application.name=users-ws eureka.client.service-url.defaultZone=http://localhost:8086/eureka eureka.instance.instance-id=${spring.application.name}:${spring.application.instance_id:${random.value}} eureka.client.fetch-registry=true eureka.client.register-with-eureka=true eureka.client.enabled=true gateway.ip=192.168.2.184
错误分析
- DiscoveryClient方法调用错误:
getInstancesById()是根据服务的instance-id查询实例,而非服务名。传入的USERS-WS是Eureka中显示的服务名,不是实例ID,因此无法找到实例。 - WebClient未集成服务发现:当前WebClient直接通过DNS解析服务名
users-ws,没有利用Eureka的服务发现机制,导致DNS无法识别内部服务名。 - 服务名大小写一致性问题:Eureka默认会将
spring.application.name转换为大写存储,调用时需匹配该格式。
解决方案
1. 修正DiscoveryClient实例查询方法
将getInstancesById()替换为getInstances(),传入Eureka中注册的服务名(大写USERS-WS):
// 原代码 List<InstanceInfo> instance = discoveryClient.getInstancesById("USERS-WS"); // 修改后 List<InstanceInfo> instances = discoveryClient.getInstances("USERS-WS");
可添加日志验证已注册服务列表,确认是否拉取到目标服务:
log.info("已注册服务列表: " + discoveryClient.getServices());
2. 配置WebClient支持负载均衡与服务发现
在chat-ws中创建WebClient配置类,添加@LoadBalanced注解,让WebClient能够通过Eureka解析服务名:
@Configuration public class WebClientConfig { @Bean @LoadBalanced public WebClient.Builder webClientBuilder() { return WebClient.builder(); } @Bean public WebClient webClient(WebClient.Builder webClientBuilder) { return webClientBuilder.build(); } }
确保注入的WebClient是通过该配置类创建的,而非直接实例化。
3. 验证服务名一致性
Eureka控制台显示的服务名为USERS-WS,对应users-ws的spring.application.name=users-ws(Eureka自动转大写),因此调用时使用http://USERS-WS/api/user/usersdata或http://users-ws/api/user/usersdata均可(Eureka服务名大小写不敏感),建议与Eureka显示的大写格式保持一致。
4. 确认注册表拉取配置
确保chat-ws的eureka.client.fetch-registry=true已正确配置,该配置决定服务是否从Eureka拉取注册表信息。若仍有问题,可添加eureka.client.registry-fetch-interval-seconds=5缩短注册表拉取间隔,加速服务发现。
验证步骤
- 重启chat-ws和users-ws服务
- 调用
getUsersData()方法,检查日志是否能获取到users-ws实例 - 查看WebClient调用是否成功返回响应
内容的提问来源于stack exchange,提问作者Hubert Kobos

