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