序
本文主要研究一下ribbon的超時(shí)時(shí)間設(shè)置
配置
實(shí)例
ribbon:
ReadTimeout: 10000
ConnectTimeout: 10000
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 1
eureka:
enabled: true
RibbonClientConfiguration
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonClientConfiguration.java
@SuppressWarnings("deprecation")
@Configuration
@EnableConfigurationProperties
//Order is important here, last should be the default, first should be optional
// see https://github.com/spring-cloud/spring-cloud-netflix/issues/2086#issuecomment-316281653
@Import({HttpClientConfiguration.class, OkHttpRibbonConfiguration.class, RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class})
public class RibbonClientConfiguration {
public static final int DEFAULT_CONNECT_TIMEOUT = 1000;
public static final int DEFAULT_READ_TIMEOUT = 1000;
@RibbonClientName
private String name = "client";
// TODO: maybe re-instate autowired load balancers: identified by name they could be
// associated with ribbon clients
@Autowired
private PropertiesFactory propertiesFactory;
@Bean
@ConditionalOnMissingBean
public IClientConfig ribbonClientConfig() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.loadProperties(this.name);
config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT);
config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT);
return config;
}
//......
}
- 這里設(shè)置默認(rèn)的超時(shí)值,都是1000毫秒,設(shè)置在DefaultClientConfigImpl
AbstractLoadBalancingClient
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/support/AbstractLoadBalancingClient.java
public abstract class AbstractLoadBalancingClient<S extends ContextAwareRequest, T extends IResponse, D> extends
AbstractLoadBalancerAwareClient<S, T> implements ServiceInstanceChooser {
protected int connectTimeout;
protected int readTimeout;
//......
@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();
}
//......
}
- 這里從RibbonProperties讀取超時(shí)參數(shù),然后放到類成員變量connectTimeout及readTimeout
- RibbonProperties就最后是從IClientConfig讀取
RibbonLoadBalancingHttpClient
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/apache/RibbonLoadBalancingHttpClient.java
// TODO: rename (ie new class that extends this in Dalston) to ApacheHttpLoadBalancingClient
public class RibbonLoadBalancingHttpClient extends
AbstractLoadBalancingClient<RibbonApacheHttpRequest, RibbonApacheHttpResponse, CloseableHttpClient> {
//......
@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());
}
//......
}
- 這里execute方法從IClientConfig構(gòu)造RequestConfig,會(huì)設(shè)置connectTimeout及socketTimeout
- 如果configOverride為null椒拗,則使用抽象類的默認(rèn)配置
OkHttpLoadBalancingClient
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/okhttp/OkHttpLoadBalancingClient.java
public class OkHttpLoadBalancingClient
extends AbstractLoadBalancingClient<OkHttpRibbonRequest, OkHttpRibbonResponse, 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();
}
//......
}
- 這里是通過configOverride或默認(rèn)的config來構(gòu)建指定超時(shí)參數(shù)的OkHttpClient
- 相比較于apache httpclient通過request config來設(shè)置超時(shí)時(shí)間,OkHttpClient是通過client來設(shè)置的,這樣可能存在一個(gè)問題兵琳,就是OkHttpClient沒法用單例,每次都得new一個(gè)
clientConfig傳遞
RibbonHttpRequest
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonHttpRequest.java
public class RibbonHttpRequest extends AbstractClientHttpRequest {
//......
@Override
protected ClientHttpResponse executeInternal(HttpHeaders headers)
throws IOException {
try {
addHeaders(headers);
if (outputStream != null) {
outputStream.close();
builder.entity(outputStream.toByteArray());
}
HttpRequest request = builder.build();
HttpResponse response = client.executeWithLoadBalancer(request, config);
return new RibbonHttpResponse(response);
} catch (Exception e) {
throw new IOException(e);
}
}
//......
}
- 這里client.executeWithLoadBalancer(request, config)使用的是RibbonHttpRequest的config配置
RibbonClientHttpRequestFactory
spring-cloud-netflix-ribbon-2.0.0.RELEASE-sources.jar!/org/springframework/cloud/netflix/ribbon/RibbonClientHttpRequestFactory.java
public class RibbonClientHttpRequestFactory implements ClientHttpRequestFactory {
private final SpringClientFactory clientFactory;
public RibbonClientHttpRequestFactory(SpringClientFactory clientFactory) {
this.clientFactory = clientFactory;
}
@Override
@SuppressWarnings("deprecation")
public ClientHttpRequest createRequest(URI originalUri, HttpMethod httpMethod)
throws IOException {
String serviceId = originalUri.getHost();
if (serviceId == null) {
throw new IOException(
"Invalid hostname in the URI [" + originalUri.toASCIIString() + "]");
}
IClientConfig clientConfig = this.clientFactory.getClientConfig(serviceId);
RestClient client = this.clientFactory.getClient(serviceId, RestClient.class);
HttpRequest.Verb verb = HttpRequest.Verb.valueOf(httpMethod.name());
return new RibbonHttpRequest(originalUri, verb, client, clientConfig);
}
}
- ClientHttpRequest是通過RibbonClientHttpRequestFactory這個(gè)工廠創(chuàng)建的
- clientConfig是RibbonClientHttpRequestFactory這個(gè)工廠根據(jù)serviceId獲取的骇径,默認(rèn)是DefaultClientConfigImpl躯肌,從配置文件讀取,serviceId自己的個(gè)性化配置參數(shù)會(huì)覆蓋默認(rèn)值破衔,讀取不到的就是默認(rèn)的參數(shù)清女。
小結(jié)
spring cloud netflix的ribbon,其超時(shí)時(shí)間配置有ReadTimeout以及ConnectTimeout晰筛,分別是設(shè)置的socketTimeout以及connectTimeout嫡丙,創(chuàng)建請(qǐng)求的時(shí)候,會(huì)讀取指定配置读第,沒有的話曙博,就取默認(rèn)的配置,設(shè)置超時(shí)時(shí)間怜瞒。