Spring Cloud Consul 3.1.1中spring.cloud.consul.host属性解析兼容性故障
Spring Cloud Consul 3.1.1 升级后host配置含端口导致无效URI问题
问题背景
我们将基于Consul的Spring Boot应用从spring-boot:2.1.4.RELEASE升级至spring-boot:2.7.3后,遭遇Spring Cloud Consul兼容性问题:
- 旧版本
spring-cloud-consul-core:2.1.1中,spring.cloud.consul.host配置项可直接包含端口(例如https://xyz:8610) - 升级到
spring-cloud-consul:3.1.1后,系统强制要求单独配置spring.cloud.consul.port;若未配置,则自动追加Consul默认端口8500,最终生成无效URI(如https://<xyz.com>:8610:8500/v1/kv/abc/services) - 应用内部存在基于单属性
host:port的自定义逻辑,该变更直接阻碍了升级进程,需确认此是否为Spring Cloud的强制变更
错误详情
[ERROR] 2023-01-08 16:12:33,644 [main] org.springframework.boot.SpringApplication org.springframework.boot.SpringApplication Application run failed org.springframework.cloud.consul.config.ConsulPropertySources$PropertySourceNotFoundException: com.ecwid.consul.transport.TransportException: org.apache.http.client.ClientProtocolException: URI does not specify a valid host name: https://<xyz.com>:8610:8500/v1/kv/abc/services/xyz-service/?recurse&token=yyy-xxx at org.springframework.cloud.consul.config.ConsulPropertySources.createPropertySource(ConsulPropertySources.java:143) at org.springframework.cloud.consul.config.ConsulPropertySourceLocator.locate(ConsulPropertySourceLocator.java:88) at org.springframework.cloud.bootstrap.config.PropertySourceLocator.locateCollection(PropertySourceLocator.java:51) at org.springframework.cloud.consul.config.ConsulPropertySourceLocator.locateCollection(ConsulPropertySourceLocator.java:71) at org.springframework.cloud.consul.config.ConsulPropertySourceLocator$$FastClassBySpringCGLIB$$b35ebf8.invoke(<generated>) ... Caused by: com.ecwid.consul.transport.TransportException: org.apache.http.client.ClientProtocolException: URI does not specify a valid host name: https://rn-spindlet-lapp21.rno.apple.com:8610:8500/v1/kv/rins/services/file-service,aluminum-prod-logging/?recurse&token=e23d8856-cfb3-2d2e-6fd2-e2ed3ab6f341 at com.ecwid.consul.transport.AbstractHttpTransport.executeRequest(AbstractHttpTransport.java:83) at com.ecwid.consul.transport.AbstractHttpTransport.makeGetRequest(AbstractHttpTransport.java:36) at com.ecwid.consul.v1.ConsulRawClient.makeGetRequest(ConsulRawClient.java:139) at com.ecwid.consul.v1.ConsulRawClient.makeGetRequest(ConsulRawClient.java:128) at com.ecwid.consul.v1.kv.KeyValueConsulClient.getKVValues(KeyValueConsulClient.java:147) at com.ecwid.consul.v1.ConsulClient.getKVValues(ConsulClient.java:644)
当前bootstrap配置
spring: cloud: consul: config: format: YAML data-key: local enabled: true prefix: abc/services host: https://xyz:8610 token: xxx tls: keyStoreInstanceType: PKCS12 certificatePath: /abc/keystore certificatePassword: rrr keyStorePath: /abc/keystore keyStorePassword: rrr
原因分析
该行为变更是Spring Cloud Consul 3.x版本的强制调整。对应Spring Cloud 2021.0.x版本的Consul 3.1.x中,spring.cloud.consul.host的解析逻辑被修改:不再自动从host配置中提取端口,要求单独通过spring.cloud.consul.port配置端口;若未配置port,则默认使用8500,导致原本包含端口的host被重复拼接端口,生成无效URI。
解决方案
方案1:拆分host与port配置(需调整自定义逻辑)
修改bootstrap配置,将host中的端口拆分到单独的port属性:
spring: cloud: consul: host: https://xyz port: 8610 # 其他配置保持不变
此方案需同步调整应用内部基于host:port的自定义逻辑,适配拆分后的配置项。
方案2:自定义配置兼容旧逻辑(无需修改自定义代码)
通过自定义配置类,重新实现host和port的解析逻辑,兼容旧版本行为:
import org.springframework.cloud.consul.ConsulProperties; import org.springframework.cloud.consul.client.ConsulClientFactory; import org.springframework.cloud.consul.client.DefaultConsulClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; import java.net.URI; import java.net.URISyntaxException; @Configuration public class ConsulCompatConfig { @Bean public ConsulClientFactory consulClientFactory(ConsulProperties properties) { String host = properties.getHost(); if (StringUtils.hasText(host) && host.startsWith("http")) { try { URI uri = new URI(host); // 提取host地址(含协议) properties.setHost(uri.getScheme() + "://" + uri.getHost()); // 提取端口并覆盖配置 properties.setPort(uri.getPort()); } catch (URISyntaxException e) { // 解析失败时沿用原有逻辑 } } return new DefaultConsulClientFactory(properties); } }
该配置类会在初始化ConsulClient前,自动从原host配置中提取端口并设置到port属性,保持与旧版本一致的行为,无需修改应用内部自定义逻辑。
方案3:降级Spring Cloud Consul版本(不推荐)
若暂时无法适配新逻辑,可考虑降级到兼容版本,但此方案会错过新版本的特性与问题修复,仅作为临时应急方案。
结论
该变更是Spring Cloud Consul 3.x版本的强制行为调整,目的是规范配置项职责划分(host仅存储主机地址,port单独配置端口)。推荐使用方案2兼容旧有逻辑,同时完成版本升级。
内容的提问来源于stack exchange,提问作者sanjay
相关产品推荐
相关产品推荐

