博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
聊聊spring cloud的AbstractLoadBalancingClient
阅读量:6084 次
发布时间:2019-06-20

本文共 18788 字,大约阅读时间需要 62 分钟。

本文主要研究一下spring cloud的AbstractLoadBalancingClient

AbstractLoadBalancingClient

spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/support/AbstractLoadBalancingClient.java

/** * @author Spencer Gibb */public abstract class AbstractLoadBalancingClient extends        AbstractLoadBalancerAwareClient
implements ServiceInstanceChooser { protected int connectTimeout; protected int readTimeout; protected boolean secure; protected boolean followRedirects; protected boolean okToRetryOnAllOperations; protected final D delegate; protected final IClientConfig config; protected final ServerIntrospector serverIntrospector; public boolean isClientRetryable(ContextAwareRequest request) { return false; } protected AbstractLoadBalancingClient(IClientConfig config, ServerIntrospector serverIntrospector) { super(null); this.delegate = createDelegate(config); this.config = config; this.serverIntrospector = serverIntrospector; this.setRetryHandler(RetryHandler.DEFAULT); initWithNiwsConfig(config); } protected AbstractLoadBalancingClient(D delegate, IClientConfig config, ServerIntrospector serverIntrospector) { super(null); this.delegate = delegate; this.config = config; this.serverIntrospector = serverIntrospector; this.setRetryHandler(RetryHandler.DEFAULT); initWithNiwsConfig(config); } @Override public void initWithNiwsConfig(IClientConfig clientConfig) { super.initWithNiwsConfig(clientConfig); RibbonProperties ribbon = RibbonProperties.from(clientConfig); this.connectTimeout = ribbon.connectTimeout(DEFAULT_CONNECT_TIMEOUT); this.readTimeout = ribbon.readTimeout(DEFAULT_READ_TIMEOUT); this.secure = ribbon.isSecure(); this.followRedirects = ribbon.isFollowRedirects(); this.okToRetryOnAllOperations = ribbon.isOkToRetryOnAllOperations(); } protected abstract D createDelegate(IClientConfig config); public D getDelegate() { return this.delegate; } @Override public RequestSpecificRetryHandler getRequestSpecificRetryHandler( final S request, final IClientConfig requestConfig) { if (this.okToRetryOnAllOperations) { return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig); } if (!request.getContext().getMethod().equals("GET")) { return new RequestSpecificRetryHandler(true, false, this.getRetryHandler(), requestConfig); } else { return new RequestSpecificRetryHandler(true, true, this.getRetryHandler(), requestConfig); } } protected boolean isSecure(final IClientConfig config) { if(config != null) { return RibbonProperties.from(config).isSecure(this.secure); } return this.secure; } @Override protected void customizeLoadBalancerCommandBuilder(S request, IClientConfig config, LoadBalancerCommand.Builder
builder) { if (request.getLoadBalancerKey() != null) { builder.withServerLocator(request.getLoadBalancerKey()); } } @Override public ServiceInstance choose(String serviceId) { Server server = this.getLoadBalancer().chooseServer(serviceId); if (server != null) { return new RibbonLoadBalancerClient.RibbonServer(serviceId, server); } return null; } public void validateServiceInstance(ServiceInstance serviceInstance) throws ClientException { if (serviceInstance == null) { throw new ClientException("Load balancer does not have available server for client: " + clientName); } else if (serviceInstance.getHost() == null) { throw new ClientException("Invalid Server for: " + serviceInstance.getServiceId() + " null Host"); } }}
  • AbstractLoadBalancingClient继承了AbstractLoadBalancerAwareClient,实现了ServiceInstanceChooser接口
  • 它有两个基本的实现,分别是使用apache httpclient的RibbonLoadBalancingHttpClient,以及使用okhttp的OkHttpLoadBalancingClient

RibbonLoadBalancingHttpClient

spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/apache/RibbonLoadBalancingHttpClient.java

/** * @author Christian Lohmann * @author Ryan Baxter * @author Tim Ysewyn */// TODO: rename (ie new class that extends this in Dalston) to ApacheHttpLoadBalancingClientpublic class RibbonLoadBalancingHttpClient extends        AbstractLoadBalancingClient
{ public RibbonLoadBalancingHttpClient(IClientConfig config, ServerIntrospector serverIntrospector) { super(config, serverIntrospector); } public RibbonLoadBalancingHttpClient(CloseableHttpClient delegate, IClientConfig config, ServerIntrospector serverIntrospector) { super(delegate, config, serverIntrospector); } protected CloseableHttpClient createDelegate(IClientConfig config) { RibbonProperties ribbon = RibbonProperties.from(config); return HttpClientBuilder.create() // already defaults to 0 in builder, so resetting to 0 won't hurt .setMaxConnTotal(ribbon.maxTotalConnections(0)) // already defaults to 0 in builder, so resetting to 0 won't hurt .setMaxConnPerRoute(ribbon.maxConnectionsPerHost(0)) .disableCookieManagement().useSystemProperties() // for proxy .build(); } @Override public RibbonApacheHttpResponse execute(RibbonApacheHttpRequest request, final IClientConfig configOverride) throws Exception { IClientConfig config = configOverride != null ? configOverride : this.config; RibbonProperties ribbon = RibbonProperties.from(config); RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(ribbon.connectTimeout(this.connectTimeout)) .setSocketTimeout(ribbon.readTimeout(this.readTimeout)) .setRedirectsEnabled(ribbon.isFollowRedirects(this.followRedirects)) .build(); request = getSecureRequest(request, configOverride); final HttpUriRequest httpUriRequest = request.toRequest(requestConfig); final HttpResponse httpResponse = this.delegate.execute(httpUriRequest); return new RibbonApacheHttpResponse(httpResponse, httpUriRequest.getURI()); } @Override public URI reconstructURIWithServer(Server server, URI original) { URI uri = updateToSecureConnectionIfNeeded(original, this.config, this.serverIntrospector, server); return super.reconstructURIWithServer(server, uri); } @Override public RequestSpecificRetryHandler getRequestSpecificRetryHandler( RibbonApacheHttpRequest request, IClientConfig requestConfig) { return new RequestSpecificRetryHandler(false, false, RetryHandler.DEFAULT, requestConfig); } protected RibbonApacheHttpRequest getSecureRequest(RibbonApacheHttpRequest request, IClientConfig configOverride) { if (isSecure(configOverride)) { final URI secureUri = UriComponentsBuilder.fromUri(request.getUri()) .scheme("https").build(true).toUri(); return request.withNewUri(secureUri); } return request; }}
  • 这个类被命名为ApacheHttpLoadBalancingClient更好一点
  • execute方法将RibbonApacheHttpRequest转换为HttpUriRequest,然后使用apache httpclient进行请求

OkHttpLoadBalancingClient

spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpLoadBalancingClient.java

/** * @author Spencer Gibb * @author Ryan Baxter * @author Tim Ysewyn */public class OkHttpLoadBalancingClient        extends AbstractLoadBalancingClient
{ public OkHttpLoadBalancingClient(IClientConfig config, ServerIntrospector serverIntrospector) { super(config, serverIntrospector); } public OkHttpLoadBalancingClient(OkHttpClient delegate, IClientConfig config, ServerIntrospector serverIntrospector) { super(delegate, config, serverIntrospector); } @Override protected OkHttpClient createDelegate(IClientConfig config) { return new OkHttpClient(); } @Override public OkHttpRibbonResponse execute(OkHttpRibbonRequest ribbonRequest, final IClientConfig configOverride) throws Exception { boolean secure = isSecure(configOverride); if (secure) { final URI secureUri = UriComponentsBuilder.fromUri(ribbonRequest.getUri()) .scheme("https").build().toUri(); ribbonRequest = ribbonRequest.withNewUri(secureUri); } OkHttpClient httpClient = getOkHttpClient(configOverride, secure); final Request request = ribbonRequest.toRequest(); Response response = httpClient.newCall(request).execute(); return new OkHttpRibbonResponse(response, ribbonRequest.getUri()); } OkHttpClient getOkHttpClient(IClientConfig configOverride, boolean secure) { IClientConfig config = configOverride != null ? configOverride : this.config; RibbonProperties ribbon = RibbonProperties.from(config); OkHttpClient.Builder builder = this.delegate.newBuilder() .connectTimeout(ribbon.connectTimeout(this.connectTimeout), TimeUnit.MILLISECONDS) .readTimeout(ribbon.readTimeout(this.readTimeout), TimeUnit.MILLISECONDS) .followRedirects(ribbon.isFollowRedirects(this.followRedirects)); if (secure) { builder.followSslRedirects(ribbon.isFollowRedirects(this.followRedirects)); } return builder.build(); } @Override public URI reconstructURIWithServer(Server server, URI original) { URI uri = updateToSecureConnectionIfNeeded(original, this.config, this.serverIntrospector, server); return super.reconstructURIWithServer(server, uri); }}
  • OkHttpLoadBalancingClient里头根据IClientConfig构建OkHttpClient,然后再将响应包装为OkHttpRibbonResponse

配置

HttpClientRibbonConfiguration

spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/apache/HttpClientRibbonConfiguration.java

@Configuration@ConditionalOnClass(name = "org.apache.http.client.HttpClient")@ConditionalOnProperty(name = "ribbon.httpclient.enabled", matchIfMissing = true)public class HttpClientRibbonConfiguration {    @RibbonClientName    private String name = "client";    @Configuration    protected static class ApacheHttpClientConfiguration {        private final Timer connectionManagerTimer = new Timer(                "RibbonApacheHttpClientConfiguration.connectionManagerTimer", true);        private CloseableHttpClient httpClient;        @Autowired(required = false)        private RegistryBuilder registryBuilder;        @Bean        @ConditionalOnMissingBean(HttpClientConnectionManager.class)        public HttpClientConnectionManager httpClientConnectionManager(                IClientConfig config,                ApacheHttpClientConnectionManagerFactory connectionManagerFactory) {            RibbonProperties ribbon = RibbonProperties.from(config);            int maxTotalConnections = ribbon.maxTotalConnections();            int maxConnectionsPerHost = ribbon.maxConnectionsPerHost();            int timerRepeat = ribbon.connectionCleanerRepeatInterval();            long timeToLive = ribbon.poolKeepAliveTime();            TimeUnit ttlUnit = ribbon.getPoolKeepAliveTimeUnits();            final HttpClientConnectionManager connectionManager = connectionManagerFactory                    .newConnectionManager(false, maxTotalConnections,                            maxConnectionsPerHost, timeToLive, ttlUnit, registryBuilder);            this.connectionManagerTimer.schedule(new TimerTask() {                @Override                public void run() {                    connectionManager.closeExpiredConnections();                }            }, 30000, timerRepeat);            return connectionManager;        }        @Bean        @ConditionalOnMissingBean(CloseableHttpClient.class)        public CloseableHttpClient httpClient(ApacheHttpClientFactory httpClientFactory,                                              HttpClientConnectionManager connectionManager, IClientConfig config) {            RibbonProperties ribbon = RibbonProperties.from(config);            Boolean followRedirects = ribbon.isFollowRedirects();            Integer connectTimeout = ribbon.connectTimeout();            RequestConfig defaultRequestConfig = RequestConfig.custom()                    .setConnectTimeout(connectTimeout)                    .setRedirectsEnabled(followRedirects).build();            this.httpClient = httpClientFactory.createBuilder().                    setDefaultRequestConfig(defaultRequestConfig).                    setConnectionManager(connectionManager).build();            return httpClient;        }        @PreDestroy        public void destroy() throws Exception {            connectionManagerTimer.cancel();            if(httpClient != null) {                httpClient.close();            }        }    }    @Bean    @ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)    @ConditionalOnMissingClass(value = "org.springframework.retry.support.RetryTemplate")    public RibbonLoadBalancingHttpClient ribbonLoadBalancingHttpClient(        IClientConfig config, ServerIntrospector serverIntrospector,        ILoadBalancer loadBalancer, RetryHandler retryHandler, CloseableHttpClient httpClient) {        RibbonLoadBalancingHttpClient client = new RibbonLoadBalancingHttpClient(httpClient, config, serverIntrospector);        client.setLoadBalancer(loadBalancer);        client.setRetryHandler(retryHandler);        Monitors.registerObject("Client_" + this.name, client);        return client;    }    @Bean    @ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)    @ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")    public RetryableRibbonLoadBalancingHttpClient retryableRibbonLoadBalancingHttpClient(            IClientConfig config, ServerIntrospector serverIntrospector,            ILoadBalancer loadBalancer, RetryHandler retryHandler,            LoadBalancedRetryFactory loadBalancedRetryFactory, CloseableHttpClient httpClient) {        RetryableRibbonLoadBalancingHttpClient client = new RetryableRibbonLoadBalancingHttpClient(            httpClient, config, serverIntrospector, loadBalancedRetryFactory);        client.setLoadBalancer(loadBalancer);        client.setRetryHandler(retryHandler);        Monitors.registerObject("Client_" + this.name, client);        return client;    }}
  • 配置的是RibbonLoadBalancingHttpClient,如果有retry,则是RetryableRibbonLoadBalancingHttpClient

OkHttpRibbonConfiguration

spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpRibbonConfiguration.java

@Configuration@ConditionalOnProperty("ribbon.okhttp.enabled")@ConditionalOnClass(name = "okhttp3.OkHttpClient")public class OkHttpRibbonConfiguration {    @RibbonClientName    private String name = "client";    @Configuration    protected static class OkHttpClientConfiguration {        private OkHttpClient httpClient;        @Bean        @ConditionalOnMissingBean(ConnectionPool.class)        public ConnectionPool httpClientConnectionPool(IClientConfig config,                                                       OkHttpClientConnectionPoolFactory connectionPoolFactory) {            RibbonProperties ribbon = RibbonProperties.from(config);            int maxTotalConnections = ribbon.maxTotalConnections();            long timeToLive = ribbon.poolKeepAliveTime();            TimeUnit ttlUnit = ribbon.getPoolKeepAliveTimeUnits();            return connectionPoolFactory.create(maxTotalConnections, timeToLive, ttlUnit);        }        @Bean        @ConditionalOnMissingBean(OkHttpClient.class)        public OkHttpClient client(OkHttpClientFactory httpClientFactory,                                   ConnectionPool connectionPool, IClientConfig config) {            RibbonProperties ribbon = RibbonProperties.from(config);            this.httpClient = httpClientFactory.createBuilder(false)                    .connectTimeout(ribbon.connectTimeout(), TimeUnit.MILLISECONDS)                    .readTimeout(ribbon.readTimeout(), TimeUnit.MILLISECONDS)                    .followRedirects(ribbon.isFollowRedirects())                    .connectionPool(connectionPool)                    .build();            return this.httpClient;        }        @PreDestroy        public void destroy() {            if(httpClient != null) {                httpClient.dispatcher().executorService().shutdown();                httpClient.connectionPool().evictAll();            }        }    }    @Bean    @ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)    @ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")    public RetryableOkHttpLoadBalancingClient retryableOkHttpLoadBalancingClient(        IClientConfig config,        ServerIntrospector serverIntrospector,        ILoadBalancer loadBalancer,        RetryHandler retryHandler,        LoadBalancedRetryFactory loadBalancedRetryFactory,        OkHttpClient delegate) {        RetryableOkHttpLoadBalancingClient client = new RetryableOkHttpLoadBalancingClient(delegate, config,                serverIntrospector, loadBalancedRetryFactory);        client.setLoadBalancer(loadBalancer);        client.setRetryHandler(retryHandler);        Monitors.registerObject("Client_" + this.name, client);        return client;    }    @Bean    @ConditionalOnMissingBean(AbstractLoadBalancerAwareClient.class)    @ConditionalOnMissingClass(value = "org.springframework.retry.support.RetryTemplate")    public OkHttpLoadBalancingClient okHttpLoadBalancingClient(        IClientConfig config,        ServerIntrospector serverIntrospector, ILoadBalancer loadBalancer,        RetryHandler retryHandler, OkHttpClient delegate) {        OkHttpLoadBalancingClient client = new OkHttpLoadBalancingClient(delegate, config,                serverIntrospector);        client.setLoadBalancer(loadBalancer);        client.setRetryHandler(retryHandler);        Monitors.registerObject("Client_" + this.name, client);        return client;    }}
  • 配置的是OkHttpLoadBalancingClient,如果有retry,则是RetryableOkHttpLoadBalancingClient

小结

AbstractLoadBalancingClient有appche httpclient以及okhttp两类实现,分别是RibbonLoadBalancingHttpClient及OkHttpLoadBalancingClient;每种实现都有retry相关的实现,分别是RetryableRibbonLoadBalancingHttpClient、RetryableOkHttpLoadBalancingClient。

doc

转载地址:http://rmkwa.baihongyu.com/

你可能感兴趣的文章
exchange 2010 队列删除
查看>>
「翻译」逐步替换Sass
查看>>
H5实现全屏与F11全屏
查看>>
处理excel表的列
查看>>
C#数据采集类
查看>>
quicksort
查看>>
【BZOJ2019】nim
查看>>
四部曲
查看>>
LINUX内核调试过程
查看>>
【HDOJ】3553 Just a String
查看>>
Java 集合深入理解(7):ArrayList
查看>>
2019年春季学期第四周作业
查看>>
linux环境配置
查看>>
ASP.NET MVC中从前台页面视图(View)传递数据到后台控制器(Controller)方式
查看>>
一个想法(续二):换个角度思考如何解决IT企业招聘难的问题!
查看>>
tomcat指定配置文件路径方法
查看>>
linux下查看各硬件型号
查看>>
epoll的lt和et模式的实验
查看>>
Flux OOM实例
查看>>
07-k8s-dns
查看>>