You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 21:15:36