问题
I am using
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.2.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
My main class:
@SpringBootApplication
//@Configuration
@ComponentScan(basePackages = "com.mypackage")
@EnableAutoConfiguration
@EnableEurekaClient
@EnableSwagger2
public class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class, args);
}
@LoadBalanced
@Bean(name="template")
RestTemplate restTemplate() {
return new RestTemplate();
}
}
My service calling:
@Autowired
private RestTemplate template;
ResponseEntity<String> avs = template.exchange("http://localhost:7075/xyz/json/authenticate",HttpMethod.POST ,request,String.class);
It is throwing the following exception
java.lang.IllegalStateException: No instances available for localhost
at org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient.execute(RibbonLoadBalancerClient.java:90)
at org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor$1.doWithRetry(RetryLoadBalancerInterceptor.java:60)
at org.springframework.cloud.client.loadbalancer.RetryLoadBalancerInterceptor$1.doWithRetry(RetryLoadBalancerInterceptor.java:48)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:276)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:157)
回答1:
When you use a @LoadBalanced
RestTemplate
the hostname needs to be a serviceId not an actual hostname. In your case, it's trying to find a eureka record for localhost
and can't find one. See the documentation for how to use multiple RestTemplate
objects, one load balanced, one not.
@Configuration
public class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate loadBalanced() {
return new RestTemplate();
}
@Primary
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
public class MyClass {
@Autowired
private RestTemplate restTemplate;
@Autowired
@LoadBalanced
private RestTemplate loadBalanced;
public String doOtherStuff() {
return loadBalanced.getForObject("http://stores/stores", String.class);
}
public String doStuff() {
return restTemplate.getForObject("http://example.com", String.class);
}
}
回答2:
From what I read there is some kind of problem when you try to Autowire RestTemplate while using this Netflix cloud. However I found a workaround. First declare a new @Component class and in it create a method that returns RestTemplate:
@Component
public class RestTemplateComponentFix{
@Autowired
SomeConfigurationYouNeed someConfiguration;
@LoadBalanced
public RestTemplate getRestTemplate() {
// TODO set up your restTemplate
rt.setRequestFactory( new HttpComponentsClientHttpRequestFactory() );
return rt;
}
}
After that just Autowire the restTemplateComponentFix in your class and when when you need the rest template call the restTemplate() method. Something like this:
@Service
public class someClass{
@Autowired
RestTemplateComponentFix restTemplateComponentFix;
public void methodUsingRestTemplate(){
// Some code...
RestTemplate rt = restTemplateComponentFix.getRestTemplate();
// Some code...
}
}
The cool part is that you can easily unit test this code with something like:
RestTemplate rt = Mockito.mock(RestTemplate.class)
when(restTemplateComponentFix.getRestTemplate()).thenReturn(rt);
when(rt.someMethod()).thenReturn(something);
来源:https://stackoverflow.com/questions/41569558/ribbon-with-spring-cloud-and-eureka-java-lang-illegalstateexception-no-instance