SpringBoot3下Spring Cloud Config Server无法注册到Eureka的认证问题
在Spring Boot 3.0.0、Spring Cloud 2022.0.0-RC2环境中,Spring Cloud Config Server无法注册到开启用户名密码认证的Eureka注册中心。已在Config Server的eureka.client.serviceUrl.defaultZone中配置带认证信息的地址,但启动时控制台报错AuthScheme is null,且无法发送心跳。相同代码在Spring Boot 2.6版本可正常运行。
相关配置及报错日志如下:
Eureka Server 配置(application.yml)
server: port: 8761 spring: application: name: eureka-server profiles: active: dev security: user: name: user password: password eureka: instance: instance-id: ${spring.application.name}:${random.uuid} client: serviceUrl: defaultZone: ${EUREKA_SERVER:http://user:password@localhost:8761/eureka} lease-renewal-interval-in-seconds: 5 registerWithEureka: true fetchRegistry: false management: endpoints: web: exposure: include: "*"
Config Server 配置(application.yml)
server: port: 8888 management: endpoints: web: exposure: include: "*" endpoint: env: post: enabled: true logging: level: com.netflix.discovery: 'DEBUG' org.springframework.cloud: 'DEBUG' spring: application: name: config-server profiles: active: dev devtools: livereload: port: 35730 jmx: enabled: true cloud: config: fail-fast: true discovery.enabled: true server: git: cloneOnStart: true uri: ${GIT_CONFIG_REPOSITORY} skipSslValidation: true default-label: master eureka: registerWithEureka: true fetchRegistry: true client: serviceUrl: defaultZone: ${EUREKA_SERVER:http://username:password@localhost:8761/eureka} instance: instance-id: ${spring.application.name}:${random.uuid}
报错日志
2022-12-11T15:15:50.152+01:00[0;39m [32m INFO[0;39m [35m15612[0;39m [2m---[0;39m [2m[ main][0;39m [36mc.n.d.s.t.d.RedirectingEurekaHttpClient [0;39m [2m:[0;39m Request execution error. endpoint=DefaultEndpoint{ serviceUrl='http://username:password@localhost:8761/eureka/}, exception=AuthScheme is null stacktrace=java.lang.IllegalStateException: AuthScheme is null at org.apache.hc.core5.util.Asserts.notNull(Asserts.java:56) ...(省略重复栈信息) 2022-12-11T15:16:20.204+01:00[0;39m [31mERROR[0;39m [35m15612[0;39m [2m---[0;39m [2m[tbeatExecutor-0][0;39m [36mcom.netflix.discovery.DiscoveryClient [0;39m [2m:[0;39m DiscoveryClient_CONFIG-SERVER/config-server:b3790bfa-41c5-42ca-8e27-b70b219c0ab9 - was unable to send heartbeat! com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server ...(省略重复栈信息)
解决方案
1. 显式配置Eureka Client的认证信息
Spring Boot 3.x升级了Apache HttpClient到5.x版本,Netflix Eureka Client不再自动解析defaultZone URL中的用户名密码来生成认证方案(AuthScheme),需要单独配置认证信息:
修改Config Server的application.yml,移除defaultZone中的用户名密码,添加eureka.client.username和eureka.client.password:
eureka: registerWithEureka: true fetchRegistry: true client: serviceUrl: defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka} # 显式配置Eureka认证用户名和密码 username: username password: password instance: instance-id: ${spring.application.name}:${random.uuid}
如果使用环境变量,可调整为:
eureka: client: serviceUrl: defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka} username: ${EUREKA_USER:username} password: ${EUREKA_PASS:password}
2. (可选)兼容URL方式的临时方案
若需保留URL中的认证信息,需手动配置HttpClient的AuthScheme,但这种方式不如显式配置规范,不推荐。可以通过自定义EurekaHttpClientFactory来实现,但步骤繁琐,优先推荐第一种方案。
原因说明
Spring Cloud 2022.0.0(Kilburn版本)基于Spring Boot 3.x,底层依赖的Apache HttpClient从4.x升级到5.x。Netflix Eureka Client在适配HttpClient5时,移除了自动解析URL中认证信息的逻辑,导致直接在defaultZone中携带username:password@的方式无法生成有效的AuthScheme,从而抛出AuthScheme is null异常。而Spring Boot 2.6版本使用的是HttpClient4.x,Eureka Client可以正常解析URL中的认证信息,因此旧版本代码可正常运行。
内容的提问来源于stack exchange,提问作者omar

