springcloud-config客户端启用服务发现报错找不到bean EurekaHttpClient

背景

在对已有项目进行改造的时候,集成SpringConfigStarter,编写完bootstrap.yml,在idea 启动项中编辑并新增VM options -Dspring.cloud.config.discovery.enabled=true,该版本不加spring不会从configService获取信息,官方建议引入一个starter,但是在我的项目中并没有用处,点击运行,报错信息如下

java 复制代码
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.netflix.discovery.shared.transport.EurekaHttpClient' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1717) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1273) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1227) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:886) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:790) ~[spring-beans-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	... 30 common frames omitted

根据堆栈信息缺失EurekaHttpClient,很容易联想到是不是依赖问题,确认了pom.xml之后发现确实引入了

xml 复制代码
       <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-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>

环境如下

SpringBoot 版本2.3.12.Release

SpringCloud 版本 Hoxton.SR12

JDK 11

再次运行依然报错,然后根据报错堆栈找到,创建的beans
org.springframework.cloud.netflix.eureka.config.EurekaConfigServerBootstrapConfiguration#eurekaConfigServerInstanceProvider该bean的第一个参数就是EurekaHttpClient,也就是创建该bean的时候EurekaHttpClient并没有完成初始化,同时注意到该Configuration的是有初始化EurekaHttpClient的逻辑的

java 复制代码
@Bean
    @ConditionalOnMissingBean(
        value = {EurekaClientConfig.class},
        search = SearchStrategy.CURRENT
    )
    public EurekaClientConfigBean eurekaClientConfigBean() {
        return new EurekaClientConfigBean();
    }

    @Bean
    @ConditionalOnMissingBean({EurekaHttpClient.class})
    @ConditionalOnProperty(
        prefix = "eureka.client",
        name = {"webclient.enabled"},
        matchIfMissing = true,
        havingValue = "false"
    )
    public RestTemplateEurekaHttpClient configDiscoveryRestTemplateEurekaHttpClient(EurekaClientConfigBean config, Environment env) {
        return (RestTemplateEurekaHttpClient)(new RestTemplateTransportClientFactory()).newClient(new DefaultEndpoint(getEurekaUrl(config, env)));
    }

 	...

    @Bean
    public ConfigServerInstanceProvider.Function eurekaConfigServerInstanceProvider(EurekaHttpClient client, EurekaClientConfig config) {
        return (serviceId) -> {
            if (log.isDebugEnabled()) {
                log.debug("eurekaConfigServerInstanceProvider finding instances for " + serviceId);
            }

            EurekaHttpResponse<Applications> response = client.getApplications(new String[]{config.getRegion()});
            List<ServiceInstance> instances = new ArrayList();
            if (this.isSuccessful(response) && response.getEntity() != null) {
                Applications applications = (Applications)response.getEntity();
                applications.shuffleInstances(config.shouldFilterOnlyUpInstances());
                List<InstanceInfo> infos = applications.getInstancesByVirtualHostName(serviceId);
                Iterator var8 = infos.iterator();

                while(var8.hasNext()) {
                    InstanceInfo info = (InstanceInfo)var8.next();
                    instances.add(new EurekaServiceInstance(info));
                }

                if (log.isDebugEnabled()) {
                    log.debug("eurekaConfigServerInstanceProvider found " + infos.size() + " instance(s) for " + serviceId + ", " + instances);
                }

                return instances;
            } else {
                return instances;
            }
        };
    }

可以看到bean RestTemplateEurekaHttpClient 通过org.springframework.cloud.netflix.eureka.config.EurekaConfigServerBootstrapConfiguration#configDiscoveryRestTemplateEurekaHttpClient 方法进行初始化,但是该方法执行有两个条件,即eureka.client.webclient.enabled=false@ConditionalOnMissingBean({EurekaHttpClient.class})当前环境不存在EurekaHttpClient,可以确定的是我在bootstrap.yml 配置了 eureka.client.webclient.enabled=false 并检查了好几次,根据Spring容器的初始化规则按照同Configuration类 bean从上往下一次初始化的原则,容器并没有执行 RestTemplateEurekaHttpClient的初始化操作。E:/.m2/repository/org/springframework/cloud/spring-cloud-netflix-eureka-client/2.2.9.RELEASE/spring-cloud-netflix-eureka-client-2.2.9.RELEASE.jar!/org/springframework/cloud/netflix/eureka/config/EurekaConfigServerBootstrapConfiguration.class:66

在代码的这里断点端上,然后找一个可以拿到ApplicationContext的地方执行一下表达式
environment.getProperty("eureka.client.webclient.enabled") result为 true,为了避免EurekaHttpClient已存在导致的不执行,这里再验证一下是否存在这个bean

从结果来看,引起RestTemplateEurekaHttpClient初始化不执行的原因就是 eureka.client.webclient.enabled=false,然后再次返回检查了所有配置文件终于再bootstrap

.yml中的dev profile部分看到配置依然显示为true

yml 复制代码
spring:
  profiles:
    include:
      - default
    active: dev
---
spring:
  profiles: default
  cloud:
    config:
      enabled: true
      discovery:
        enabled: true
        service-id: YOUR_CONFIG-SERVICE
      profile: ${spring.profiles.active}
      label: master
  application:
    name: yourAppName
logging:
  file:
    path: ${spring.application.name}/logs/
  level:
    root: debug
eureka:
  instance:
    prefer-ip-address: true
---
spring:
  profiles: dev
  security:
    user:
      name: user
      password: 123456
eureka:
  client:
    webclient:
      enabled: true
    fetch-registry: true
    service-url:
      defaultZone: http://your_eureka_host/eureka
  instance:
    metadata-map:
      user:
        name: ${spring.security.user.name}
        password: ${spring.security.user.password}

原因

因为本地bootstrap.yml 通过profiles 来区分不同的运行环境,导致我修改的一直修改的pro环境的配置,笑死。往往神奇的问题,都因为一些简单的原因导致的。记录排查过程,排解下郁闷☹

相关推荐
Y***h1873 小时前
第二章 Spring中的Bean
java·后端·spring
8***29313 小时前
解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域
java·前端·spring
多多*3 小时前
Java复习 操作系统原理 计算机网络相关 2025年11月23日
java·开发语言·网络·算法·spring·microsoft·maven
摇滚侠3 小时前
2025最新 SpringCloud 教程,从单体到集群架构,笔记02
笔记·spring cloud·架构
K***72844 小时前
开源模型应用落地-工具使用篇-Spring AI-Function Call(八)
人工智能·spring·开源
d***29246 小时前
【spring】Spring事件监听器ApplicationListener的使用与源码分析
java·后端·spring
v***5657 小时前
Spring Cloud Gateway 整合Spring Security
java·后端·spring
f***a3469 小时前
开源模型应用落地-工具使用篇-Spring AI-高阶用法(九)
人工智能·spring·开源
摇滚侠11 小时前
2025最新 SpringCloud 教程,编写微服务 API,笔记08
笔记·spring cloud·微服务
大云计算机毕设14 小时前
【2026计算机毕设选题】计算机毕设全新推荐项目选题指南(70+精选热门方向)
spring·数据分析·毕业设计·课程设计·毕设