4

I'm trying to hit external services from one of my microservices. I'm using Spring Cloud, Eureka for the registry and Spring boot as main framework.

Map<String, String> urlVariables = new HashMap<>();
    urlVariables.put("ip_address", IP);
    urlVariables.put("port", PORT);

    ResponseObject state =
            restTemplate.getForObject("http://{ip_address}:{port}/state/", ResponseObject.class, urlVariables);

From what I see, Spring Cloud injects Ribbon as the HTTP client for the Rest Template, and when I try to hit this IP (e.g: 193.172.x.x) it produces the following error:

java.lang.IllegalStateException: No instances available for 193.172.x.x 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.RestTemplate.doExecute(RestTemplate.java:567) at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:540) at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:247)

It looks like Ribbon is trying to find a microservice instance with that name instead of looking outside. Is there any way to configure Ribbon to look for external IPs, or is it only for internal use?

Amin Abu-Taleb
  • 4,423
  • 6
  • 33
  • 50

2 Answers2

5

You are injecting a @LoadBalanced version of RestTemplate. You have to ensure that your RestTemplate is a plain vanilla one. You can just create it with new RestTemplate(). If it's a bean just add a qualifier to ensure you're injecting a proper version of RestTemplate.

Marcin Grzejszczak
  • 10,624
  • 1
  • 16
  • 32
1

On thing you could try is to use the service id in your code and configure the real instances:

ResponseObject state =
            restTemplate.getForObject("http://myExternalService/state/", ResponseObject.class, urlVariables);

Than you configure a static list of endpoints for your service

myExternalService.ribbon.listOfServers=http://ip:port

This way you do not use service discovery for this service.

http://projects.spring.io/spring-cloud/docs/1.0.3/spring-cloud.html#spring-cloud-ribbon-without-eureka

Mathias Dpunkt
  • 11,594
  • 4
  • 45
  • 70
  • It does work but only if I disable eureka. Unfortunatelly I need eureka and also that service. Is there any way of making both work at the same time? – Amin Abu-Taleb Mar 07 '16 at 10:07
  • 2
    Yes, use `@LoadBalanced` for the one with ribbon like Marcin said, and label the non-eureka rest template as `@Primary`. – spencergibb Mar 07 '16 at 19:20