Spring Cloud
提供了一个接口 DiscoveryClient
, 为 Eureka
或者 consul
等注册中心去实现, getInstances
方法获取注册的实例,一个实例对应一个工程
List<ServiceInstance> getInstances(String serviceId);
|
看下接口 ServiceInstance
下面两个方法 获取 主机名(IP)/ 端口
String getHost(); int getPort();
|
注册了实例之后,使用 阻塞式同步RestTemplate
调用 或者 异步非阻塞 WebClient
调用,RestTemplate
为每个HTTP请求创建一个线程,在响应之前一直是阻塞状态,占用系统内存资源。
多个实例 @LoadBalaced
为 RestTemplate
或者 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(); } }
|