Ribbon整合Consul,出现No instances available for XXX 异常


先贴代码:

@RestController
public class CallHelloController {
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    
    @Autowired
    private RestTemplate restTemplate;

 

    @RequestMapping("/call")
    public String call(){
        ServiceInstance serviceInstance = loadBalancerClient.choose("service-producer");
        System.out.println("服务地址:" + serviceInstance.getUri());
        System.out.println("服务名称:" + serviceInstance.getServiceId());

        String callServiceResult = restTemplate.getForObject(serviceInstance.getUri().toString() + "/hello", String.class);
        System.out.println(callServiceResult);
        return callServiceResult;
    }

 

@SpringBootApplication
@EnableDiscoveryClient  //单纯的消费(不对外提供服务)可以不注册
@RibbonClient(name = "service-producer", configuration = RibbonConfig.class)
@ComponentScan(excludeFilters =
{@ComponentScan.Filter(type= FilterType.ANNOTATION, value=ExcludeFromComponentScan.class)}
        )
public class SpringCloudConsulConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringCloudConsulConsumerApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

application.properties

spring.application.name=spring-cloud-consul-producer
server.port=8802
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
#注册到consul的服务名称
spring.cloud.consul.discovery.serviceName=service-producer

实际上,/call请求映射方法存在问题;

问题是 因为  LoadBalancedClient  这里的 choose 根据 Consul注册的服务名(spring.cloud.consul.discovery.serviceName=service-producer) 命中一个服务提供者;

这里就不能使用加了LoadBalanced注解的RestTemplate对象了,因为会根据 host 去Consul查找服务提供者,这样就会抛异常 :No instances available for  XXX  ,也就是找不到指定的服务ID

原因:"服务地址:" + serviceInstance.getUri()这儿出现了问题。

即:

LoadBalancerClient进行手动的http请求;Ribbon集成了Apache HttpClient 、 OkHttp请求客户端使用;
我们不使用ribbon的时候,使用serviceInstance.getUri()访问是没问题的。
但是,当我们集成Ribbon后,就不行了。

辅助信息:

打印的信息:

服务地址:http://maq.xxxx.com:8802
服务名称:spring-cloud-consul-producer

 serviceInstance对象信息:RibbonServer{serviceId='spring-cloud-consul-producer', server=maq.xxxx.com:8802, secure=false, metadata={secure=false}}

/**
* Creates a URI from the given ServiceInstance's host:port.
* @param instance the ServiceInstance.
* @return URI of the form (secure)?https:http + "host:port".
*/
public static URI getUri(ServiceInstance instance) {
    String scheme = (instance.isSecure()) ? "https" : "http"; //http
    String uri = String.format("%s://%s:%s", scheme,         instance.getHost(), //host:maq.xxxx.com
    instance.getPort());
    return URI.create(uri);
}

 

我们访问的:http://maq.xxxx.com:8802

主要原因:LoadBalancerClient进行手动的http请求;Ribbon集成了Apache HttpClient 、 OkHttp请求客户端使用;

解决办法1:

在application.properties文件中加如下配置:

ribbon.okhttp.enabled= true
ribbon.restclient.enabled= true

 

解决办法二:

指定访问的http://serviceId/path  (多个服务配置相同的spring.application.name=serviceId)

@RequestMapping("/getPathParam1/{user}")
    public String getPathParam2(@PathVariable("user") String username){
        ServiceInstance serviceInstance = loadBalancerClient.choose("service-producer");
        System.out.println("服务地址:" + serviceInstance.getUri());
        System.out.println("服务名称:" + serviceInstance.getServiceId());
        
        String paramServiceResult = restTemplate.getForObject("http://" + serviceInstance.getServiceId().toString() + "/hello1/{user}", String.class,username);
        //String paramServiceResult = restTemplate.getForObject("http://spring-cloud-consul-producer/hello1/{user}", String.class,username);
        System.out.println(paramServiceResult);
        return paramServiceResult;
    }

 

参考链接:https://www.cnblogs.com/XingXiaoMeng/p/10958644.html

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM