本文主要介绍springcloud服务间通讯的家几种方式
通讯方式
- restTemplate访问
@GetMapping("/getProductMsg")
public String getProductMsg() {
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/msg", String.class);
log.info(result);
return result;
}
- loadBalancerClient+restTemplate访问
@Autowired
private LoadBalancerClient loadBalancerClient;
public String lbMsg() {
RestTemplate restTemplate = new RestTemplate();
ServiceInstance instance = loadBalancerClient.choose("PRODUCT");
String url = String.format("http://%s:%s", instance.getHost(), instance.getPort(),"/msg");
String result = restTemplate.getForObject(url, String.class);
log.info("response={}", result);
return result;
}
- 以上拼接url时候比较繁琐的,因此可以自己实现一个bean 可利用 @LoadBalanced 注解,直接
/**
* 利用 @LoadBalanced 注解 可在 restTemplate里面使用应用的名字 product
* @return
*/
@GetMapping("/lb3")
public String lb3() {
String result = restTemplate.getForObject("http://product:8080/msg", String.class);
log.info("response={}", result);
return result;
}
这里简单面熟下原理 @LoadBalanced的功能就是给restTemplate加上RetryLoadBalancerInterceptor 拦截器,负责把我们上面的自己获取url的工作帮我们做了.
这样我们就不用关心如何获取url.
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List<ClientHttpRequestInterceptor> list = new ArrayList<>(
restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
};
}
LoadBalancerInterceptor源码可以看到:
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
final ClientHttpRequestExecution execution) throws IOException {
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
Assert.state(serviceName != null,
"Request URI does not contain a valid hostname: " + originalUri);
return this.loadBalancer.execute(serviceName,
this.requestFactory.createRequest(request, body, execution));
}