0%

RestTemplate

Spring Cloud 提供了一个接口 DiscoveryClient , 为 Eureka 或者 consul 等注册中心去实现, getInstances 方法获取注册的实例,一个实例对应一个工程

List<ServiceInstance> getInstances(String serviceId);

看下接口 ServiceInstance 下面两个方法 获取 主机名(IP)/ 端口

String getHost();
int getPort();

注册了实例之后,使用 阻塞式同步RestTemplate 调用 或者 异步非阻塞 WebClient 调用,RestTemplate 为每个HTTP请求创建一个线程,在响应之前一直是阻塞状态,占用系统内存资源。

多个实例 @LoadBalacedRestTemplate 或者 WebClient 做负载均衡的支持,LoadBalancerInterceptor 实现 ClientHttpRequestInterceptor 接口 (intercept 方法)

ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException;

通过请求 URL 获取 host 然后使用 LoadBalancerClient 进行调用

public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {

private LoadBalancerClient loadBalancer;

@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));
}

看下 execute 方法 默认引用的是 RibbonLoadBalancerClient 通过 serviceId 和 调用的实例 ribbonServer 及 请求request 做服务调用

public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)
throws IOException {
ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
Server server = getServer(loadBalancer, hint);
if (server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
}
RibbonServer ribbonServer = new RibbonServer(serviceId, server,
isSecure(server, serviceId),
serverIntrospector(serviceId).getMetadata(server));

return execute(serviceId, ribbonServer, request);
}

配置 RestTemplate

@Configuration
public class RestTemplateConfiguration {

@LoadBalanced
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(100))
.setReadTimeout(Duration.ofMillis(500))
.requestFactory(this::requestFactory)
.build();
}
}