web-dev-qa-db-fra.com

Ruban avec Spring Cloud et Eureka: Java.lang.IllegalStateException: aucune instance disponible pour Samarths-MacBook-Pro.local

Je travaille sur l'application cliente Spring Boot Eureka avec Ribbon Load Balancer.

J'ai deux instances du serveur enregistrées avec Eureka avec le nom "TEST". Côté client, j'ai le code suivant pour récupérer le serveur depuis Eureka.

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
@RestController
public class EurekaConsumerApplication {

    @Autowired
    DiscoveryClient discoveryClient;

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/",method = RequestMethod.GET)
    String consumer(){
        InstanceInfo instance = discoveryClient.getNextServerFromEureka("TEST",        false);

        URI uri = UriComponentsBuilder.fromUriString(instance.getHomePageUrl() + "baseDir")
            .build()
            .toUri();
        String baseDir = restTemplate.getForObject(uri, String.class);

        return baseDir;

    }

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

application.yml

spring:
  application:
    name: consumer
info:
  component: Consumer to fetch configuration
server:
  port: 8090
eureka:
  instance:
   leaseRenewalIntervalInSeconds: 3
  metadataMap:
    instanceId:   ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${random.value}}}
client:
# Default values comes from   org.springframework.cloud.netflix.eurek.EurekaClientConfigBean
  region: default
  registryFetchIntervalSeconds: 5
  instanceInfoReplicationIntervalSeconds: 5
  initialInstanceInfoReplicationIntervalSeconds: 5
  serviceUrl:
    defaultZone: http://localhost:8761/eureka/
    availabilityZones:
    default: ${APPLICATION_DOMAIN:${DOMAIN:defaultZone}}

Cependant, lorsque j'atteins le point de terminaison reposant à l'aide de la commande suivante, cela donne une erreur:

curl http://localhost:8090/

Voici l'erreur:

{"exception":"Java.lang.IllegalStateException","message":"org.springframework.web.util.NestedServletException: Request processing failed; nested exception is Java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local","path":"/"}

Trace de la pile:

2015-07-22 14:37:35.005 INFO 13841 --- [tp1334391583-19] c.netflix.loadbalancer.BaseLoadBalancer : Client:Samarths-MacBook-Pro.local instantiated a LoadBalancer:DynamicServerListLoadBalancer:{NFLoadBalancer:name=Samarths-MacBook-Pro.local,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:null
2015-07-22 14:37:35.009 INFO 13841 --- [tp1334391583-19] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client Samarths-MacBook-Pro.local initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=Samarths-MacBook-Pro.local,current list of Servers=[],Load balancer stats=Zone stats: {},Server stats: []}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@681eda37
2015-07-22 14:37:35.029 WARN 13841 --- [tp1334391583-19] o.Eclipse.jetty.servlet.ServletHandler :

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is Java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:978)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:857)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:687)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.Java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.Java:790)
at org.Eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.Java:808)
at org.Eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.Java:1669)
at org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration$ApplicationContextHeaderFilter.doFilterInternal(EndpointWebMvcAutoConfiguration.Java:295)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
at org.Eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.Java:1652)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.Java:102)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
at org.Eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.Java:1652)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.Java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
at org.Eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.Java:1652)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.Java:85)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
at org.Eclipse.jetty..ServletHandler$CachedChain.doFilter(ServletHandler.Java:1652)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.Java:68)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)
at org.Eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.Java:1652)
at org.Eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.Java:585)
at org.Eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.Java:143)
at org.Eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.Java:548)
at org.Eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.Java:223)
at org.Eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.Java:1127)
at org.Eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.Java:515)
at org.Eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.Java:185)
at org.Eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.Java:1061)
at org.Eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.Java:141)
at org.Eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.Java:97)
at org.Eclipse.jetty.server.Server.handle(Server.Java:499)
at org.Eclipse.jetty.server.HttpChannel.handle(HttpChannel.Java:310)
at org.Eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.Java:257)
at org.Eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.Java:540)
at org.Eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.Java:635)
at org.Eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.Java:555)
at Java.lang.Thread.run(Thread.Java:745)
Caused by: Java.lang.IllegalStateException: No instances available for Samarths-MacBook-Pro.local
at org.springframework.cloud.netflix.ribbon.RibbonClientHttpRequestFactory.createRequest(RibbonClientHttpRequestFactory.Java:64)
at org.springframework.http.client.support.HttpAccessor.createRequest(HttpAccessor.Java:76)
at org.springframework.web.client.Rlate.doExecute(RestTemplate.Java:565)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.Java:545)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.Java:253)
at com.securityscorecard.eureka.consumer.EurekaConsumerApplication.consumer(EurekaConsumerApplication.Java:53)
at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62)
at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
at Java.lang.reflect.Method.invoke(Method.Java:497)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.Java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.Java:137)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.Java:110)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.Java:776)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.Java:705)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.Java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:959)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:893)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:966)
... 38 common frames omitted

On dirait que ma liste de serveurs est vide.

13
Samarth

Le RestTemplate que vous avez câblé automatiquement est déjà connecté au ruban. Vous effectuez donc une recherche à la main, puis RestTemplate essaie de rechercher le nom d'hôte transmis au ruban. Vous avez deux options: 1) N'utilisez pas le netflix DiscoveryClient et passez le serviceId en tant que nom d'hôte logique au ruban (http://TEST/myservice), 2) N'utilisez pas le RestTemplate autowired, créez-en un nouveau pour votre classe. Mon choix serait le n ° 1.

19
spencergibb

Je l'ai fait fonctionner. Le seul changement que j'ai dû faire était dans la façon dont j'utilisais l'API RestTemplate.

Code d'erreur:

@Autowired
RestTemplate restTemplate;

@RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
    String baseDir = restTemplate.getForObject("TEST", String.class);

    return baseDir;
}

Code de travail:

@Autowired
RestTemplate restTemplate;

@RequestMapping(value = "/",method = RequestMethod.GET)
String consumer(){
    String baseDir = restTemplate.getForObject("http://TEST", String.class);

    return baseDir;
}

Solution:

Le premier paramètre de restTemplate.getForObject doit avoir le format d'une URL. Et le nom de domaine doit être le nom du service que vous souhaitez découvrir.

Ex: http: // TEST . Ici, TEST est le nom de mon serveur enregistré dans le registre eureka

6
Samarth

La question est déjà répondue, mais j'ai trouvé une solution de contournement qui semble soignée et a résolu notre problème.

Déclarez d'abord une nouvelle classe @Component et créez-y une méthode qui renvoie RestTemplate:

@Component
public class RestTemplateComponentFix{

 @Autowired
 SomeConfigurationYouNeed someConfiguration;

 @LoadBalanced
 public RestTemplate getRestTemplate() {
       // TODO set up your restTemplate
        rt.setRequestFactory( new HttpComponentsClientHttpRequestFactory() );
        return rt;
    }

}

Après cela, il suffit de câbler automatiquement le restTemplateComponentFix dans votre classe et lorsque vous avez besoin du modèle de repos, appelez la méthode restTemplate (). Quelque chose comme ça:

@Service
public class someClass{

    @Autowired
    RestTemplateComponentFix restTemplateComponentFix;

    public void methodUsingRestTemplate(){
        // Some code...
        RestTemplate rt = restTemplateComponentFix.getRestTemplate();
        // Some code...
    }
}

Après cela, vous pouvez tester l'unité avec quelque chose comme:

RestTemplate rt = Mockito.mock(RestTemplate.class) 
when(restTemplateComponentFix.getRestTemplate()).thenReturn(rt);
when(rt.someMethod()).thenReturn(something);
3
pstoyanov