RestTemplate Ribbon 实现负载均衡实际进行调用时 uri 拼接异常

eureka 集群通过 ribbon + resttemplate 实现负载负载均衡时,可以根据服务名称找到时机的 ip:port 地址,但找到地址后没有将服务名称进行替换,实际请求为 服务名称 + ip:port + port 这是因为什么?
并且可以实现负载均衡,多次调用采用了轮询调用。
版本信息:spring cloud 2021.0.6 + spring boot 2.7.6
这是因为版本冲突导致的吗?

img

@SpringBootApplication
@EnableEurekaClient
public class CustomerOrder80Application {
    public static void main(String[] args){
        SpringApplication.run(CustomerOrder80Application.class, args);
    }

    @Bean
    @LoadBalanced // 开启负载均衡
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

img

img

根据你提供的代码来看,应该是 RestTemplate 的默认行为导致了这个问题。在默认情况下,如果你使用了 RestTemplate 进行服务调用,而服务名称没有被显式地替换,那么 RestTemplate 会将服务名称和实际的服务地址以及端口都拼接在一起形成最终的请求地址,从而导致服务名称被重复拼接的问题。

为了解决这个问题,你可以通过在创建 RestTemplate 实例时使用 LoadBalancerInterceptor 来实现服务名的替换。具体来说,你可以为 RestTemplate 注入 LoadBalancerInterceptor,并为其添加 @LoadBalanced 注解,从而开启负载均衡。

示例代码如下:

@SpringBootApplication
@EnableEurekaClient
public class CustomerOrder80Application {
    public static void main(String[] args){
        SpringApplication.run(CustomerOrder80Application.class, args);
    }
 
    @Bean
    @LoadBalanced // 开启负载均衡
    public RestTemplate restTemplate(LoadBalancerInterceptor loadBalancerInterceptor) {
        RestTemplate restTemplate = new RestTemplate();
 
        // 添加 LoadBalancerInterceptor
        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
        interceptors.add(loadBalancerInterceptor);
        restTemplate.setInterceptors(interceptors);
 
        return restTemplate;
    }
}

在这个示例代码中,我们通过为 RestTemplate 注入 LoadBalancerInterceptor 来实现服务名的替换,并使用 @LoadBalanced 注解开启负载均衡。同时,在 RestTemplate 实例创建时,我们将 LoadBalancerInterceptor 添加到了 RestTemplate 的拦截器中。

另外,关于版本冲突的问题,确保你使用的 Spring Cloud 版本与 Spring Boot 版本兼容即可。如果你有其他版本的依赖项,也需要确保它们与 Spring Cloud 和 Spring Boot 版本兼容。你可以参考 Spring Cloud 的官方文档中关于版本兼容的说明来解决该问题。