聊聊ribbon的超時(shí)時(shí)間設(shè)置

本文主要研究一下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í)間怜瞒。

doc

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末父泳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子吴汪,更是在濱河造成了極大的恐慌尘吗,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浇坐,死亡現(xiàn)場(chǎng)離奇詭異睬捶,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)近刘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門擒贸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來臀晃,“玉大人,你說我怎么就攤上這事介劫』胀铮” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵座韵,是天一觀的道長(zhǎng)险绘。 經(jīng)常有香客問我,道長(zhǎng)誉碴,這世上最難降的妖魔是什么宦棺? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮黔帕,結(jié)果婚禮上代咸,老公的妹妹穿的比我還像新娘。我一直安慰自己成黄,他們只是感情好呐芥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著奋岁,像睡著了一般思瘟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上闻伶,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天潮太,我揣著相機(jī)與錄音,去河邊找鬼虾攻。 笑死铡买,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的霎箍。 我是一名探鬼主播奇钞,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼漂坏!你這毒婦竟也來了景埃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤顶别,失蹤者是張志新(化名)和其女友劉穎谷徙,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驯绎,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡完慧,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了剩失。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屈尼。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡册着,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出脾歧,到底是詐尸還是另有隱情甲捏,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布鞭执,位于F島的核電站司顿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏兄纺。R本人自食惡果不足惜大溜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望囤热。 院中可真熱鬧猎提,春花似錦获三、人聲如沸旁蔼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棺聊。三九已至,卻和暖如春贞谓,著一層夾襖步出監(jiān)牢的瞬間限佩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工裸弦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留祟同,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓理疙,卻偏偏與公主長(zhǎng)得像晕城,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窖贤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理砖顷,服務(wù)發(fā)現(xiàn),斷路器赃梧,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • 本文參考了:http://blog.didispace.com/springcloud7/http://blog....
    WeiminSun閱讀 7,209評(píng)論 0 23
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,811評(píng)論 6 342
  • SpringMVC原理分析 Spring Boot學(xué)習(xí) 5滤蝠、Hello World探究 1、POM文件 1授嘀、父項(xiàng)目...
    jack_jerry閱讀 1,296評(píng)論 0 1
  • 序 本文主要研究一下ribbon的retry 配置 HttpClientRibbonConfiguration s...
    go4it閱讀 1,203評(píng)論 0 0