• 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

  • 相关阅读:
    SQL——UPDATE(改)
    SQL——INSERT INTO(增)
    SQL——SELECT(查)
    Python——raise引发异常
    Python——异常处理
    Python——多态、检查类型
    Python——继承
    Python——封装
    popitem()方法
    pop(D)方法
  • 原文地址:https://www.cnblogs.com/muxi0407/p/11655697.html
Copyright © 2020-2023  润新知