7

I have built a spring boot application using spring-cloud and want to use RestTemplate within my client application (which is also a microservice) so that I can continue using mockMvc for integration testing. I am a using the default ribbon/eureka/hystrix client setup with my client microservice and eureka client within the service I'm calling. This is working (once I figured out that serviceIds are what identifies a service endpoint within restTemplate). My problem is that I cant seem to change the restTemplate read nor connection timeout from what seems like a default of 300ms.

Details on the call:

`@Configuration
 @EnableAutoConfiguration
 @ComponentScan
 @EnableConfigurationProperties
 @EnableHystrix
 @EnableEurekaClient
public class Application { ... public static void main(String[] args) {} ... }

@Component
class EricComponentToDoHystrix {   // apparently this has to be a component for hystrix to work btw
    @Autowired
    RestTemplate restTemplate;
    ..
    @HystrixCommand(fallbackMethod="defaultRestTemplateCall")
    public void doRestTemplateCall() 
        ResponseEntity<String> result = restTemplate.getForEntity("http://someservice/doSomething", String.class);  // actually make a call
    ..
    }
}`

with an application.properties containing:

spring:
  cloud:
    client:
      serviceIds:
        - someservice

someservice:
  ribbon:
    #listOfServers: localhost:7080
    #NIWSServerListClassName: com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList

    # the eureka vipAddress of the target service (Disabled)
    DeploymentContextBasedVipAddresses: someservice

    # Interval to refresh the server list from the source
    ServerListRefreshInterval: 1000

    # Connect timeout used by Apache HttpClient.. apparently not by restTemplate 
    ConnectTimeout: 30000

    # Read timeout used by Apache HttpClient.. apparently not by restTemplate
    ReadTimeout: 30000

eureka:
  client:
    #Region where eureka is deployed -For AWS specify one of the AWS regions, for other datacenters specify a arbitrary string
    #indicating the region.This is normally specified as a -D option (eg) -Deureka.region=us-east-1
    region: default

    #For eureka clients running in eureka server, it needs to connect to servers in other zones
    preferSameZone: false

    us-east-1:
      availabilityZones: default

  instance:
    #Virtual host name by which the clients identifies this service
    virtualHostName: ${spring.application.name}
    appGroupName: ericGroup


# disable Ribbon's cicruit breaker and rely soley on Hystrix.
# this helps to avoid confusion.
# see https://github.com/Netflix/ribbon/issues/15
niws:
  loadbalancer:
    availabilityFilteringRule:
      filterCircuitTripped: false

Anybody know what properties I need so set to modify restTemplate's default timeouts? Documentation is very light on this subject and it seems the code just recently even allowed restTemplate to be used against ribbon/eureka spring boot defaults. Perhaps this has not been built yet.

RubesMN
  • 939
  • 1
  • 12
  • 22

2 Answers2

6

The RestTemplate you are injecting is completely vanilla except for a RibbonInterceptor that chooses the physical host in the URI for you (see https://github.com/spring-cloud/spring-cloud-netflix/blob/master/spring-cloud-netflix-core/src/main/java/org/springframework/cloud/netflix/ribbon/RibbonAutoConfiguration.java). The timeouts and other properties are controlled in the RestTemplate through the ClientHttpRequest. You probably should just inject the RibbonInterceptor into your own RestTemplate and set up a ClientHttpRequestFactory to do the timeouts, e.g.

@Component
class EricComponentToDoHystrix {
    private RestTemplate restTemplate;
    @Autowired
    public EricComponentToDoHystrix(RibbonInterceptor interceptor) {
         restTemplate = new RestTemplate();
         restTemplate.setInterceptors(Arrays.asList(interceptor));
         restTemplate.setRequestFactory(...);
    }
}
Dave Syer
  • 56,583
  • 10
  • 155
  • 143
  • Appreciate you both answering so quickly! Both this and @spencergibb's answer helped me. Knowing that ribbon's config has nothing to do with RestTemplate and that its vanilla except for RibbonInterceptor also will help for testing. I will set myself as listed above. btw, there is yet another timeout at play here and that is hystrix's execution.isolation.thread.timeoutInMilliseconds. So there are 3 timeouts in play now, Ribbon's, RestTemplate's and Hystrix's. – RubesMN Oct 09 '14 at 23:09
  • @DaveSyer Looks as if the `RibbonInterceptor` has vanished in the RELEASE version. Could you point me in the right direction of how to configure the RestTemplate now? – Dirk Lachowski Mar 25 '15 at 17:58
  • Try `LoadBalancerInterceptor`. – Dave Syer Mar 25 '15 at 18:06
  • @DirkLachowski: can you provide example of configuration that you got to work? – brain storm Aug 08 '15 at 07:16
  • 1
    @brainstorm Sure, have a look at https://gist.github.com/DirkLachowski/288edb8d28ed3dfd7120 but be also aware that you have to adjust hystrix' timeout if you push the rest template's timeout to far (sample in the second class in the gist). See https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.thread.timeoutInMilliseconds – Dirk Lachowski Aug 09 '15 at 12:30
  • @DirkLachowski: Thanks for tips. why did you use `LoadBalancerInterceptor`. Isn't `RibbonInterceptor ` is itself load balanced?. By setting the timeout on hystrix, I guess we trigger circuit breaker. isn't timeout on the HttpClient (as suggested by Dave above) is needed? what is the advance of timeout on hystrix vs http client? Thanks – brain storm Aug 10 '15 at 03:37
  • Just landed on this page when attempting the same kind of deal. Now things can be configured with: `@LoadBalanced` annotation on your RestTemplate `@Bean` definition. – Matt Oct 03 '18 at 22:35
1

Since I can't comment, I'll answer. The RestTemplate integration only uses the Ribbon LoadBalancer, not RestClient or NFHttpClient.

You no longer need spring.cloud.client.serviceIds, btw. If it is in docs, I'll remove it.

spencergibb
  • 24,471
  • 6
  • 69
  • 75
  • why is serviceIds no longer needed? what instead is the recommendation? the examples I found uses serviceIDs. can you please point to the relevant documentation? Also, please give your insights on this post when you can. http://stackoverflow.com/questions/31901054/spring-cloud-how-to-get-benefits-of-retry-load-balancing-and-circuit-breaker-f – brain storm Aug 10 '15 at 03:35
  • `serviceIds` was an early implementation that is no longer needed. What samples still have it? See https://github.com/spring-cloud-samples/customers-stores. As far as I know, this SO question is the only thing that references it. What are you trying to do? – spencergibb Aug 10 '15 at 15:34
  • These ones uses serviceIDs I suppose. The tutorials by Josh Long. https://github.com/joshlong/service-registration-and-discovery and https://github.com/joshlong/spring-doge-microservice – brain storm Aug 10 '15 at 16:29
  • I just looked through those projects and I don't see it being used. – spencergibb Aug 10 '15 at 16:42
  • if you look at `https://github.com/joshlong/service-registration-and-discovery/blob/master/passport-service/src/main/java/passport/Application.java`, you will notice that `bookmark-service` and `photo-service` are serviceIDs. In-order to call other microservices from within a microservice, serviceID is needed correct? – brain storm Aug 10 '15 at 17:25
  • even this post uses serviceIDs. please search for serviceID. http://www.kennybastani.com/2015/07/spring-cloud-docker-microservices.html – brain storm Aug 18 '15 at 18:01
  • It uses them, but as a concept, not in the yaml. I wrote the code that used `spring.cloud.client.serviceIds` and then I removed it. It isn't used anymore. You use service ids in feign or resttemplate or loadbalancer client. – spencergibb Aug 18 '15 at 18:21
  • oh may be `serviceID` is the equivalent of `name` of name in `yaml` – brain storm Aug 18 '15 at 19:21