ホームページ Java &#&チュートリアル springcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明

springcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明

Aug 02, 2018 pm 02:28 PM
java spring

この記事では、springcloud がリボンをどのように統合するかについて説明します。さまざまな springcloud コンポーネント (feign、zuul、RestTemplate) が異なる方法でリボンを統合します。この記事では、まず RestTemplate について説明します。

RestTemplateのクラス図は以下の通りです

springcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明

  • HttpAccessorは主にClientHttpRequestを作成しますHttpAccessor主要根据ClientHttpRequestFactory创建ClientHttpRequest

  • InterceptingHttpAccessor扩展了HttpAccessor,创建拦截的InterceptingClientHttpRequest,这里会设置拦截器ClientHttpRequestInterceptor,这是集成ribbon的核心,当RestTemplate发起http请求调用的时候,会先经过拦截器,然后才真正发起http请求。

拦截器ClientHttpRequestInterceptor是如何被设置的呢?在LoadBalancerAutoConfiguration类中,有如下代码:

@LoadBalanced
@Autowired(required = false)
private List<RestTemplate> restTemplates = Collections.emptyList();
ログイン後にコピー

只要加入注解@LoadBalancedRestTemplate会被注入,在没有引入spring retry组件的时候,加载如下配置:

@Configuration
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
static class LoadBalancerInterceptorConfig {
    @Bean
    public LoadBalancerInterceptor ribbonInterceptor(
        LoadBalancerClient loadBalancerClient,
        LoadBalancerRequestFactory requestFactory) {
        return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
    }

    @Bean
    @ConditionalOnMissingBean
    public RestTemplateCustomizer restTemplateCustomizer(
        final LoadBalancerInterceptor loadBalancerInterceptor) {
        return new RestTemplateCustomizer() {
            @Override
            public void customize(RestTemplate restTemplate) {
                List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                    restTemplate.getInterceptors());
                list.add(loadBalancerInterceptor);
                restTemplate.setInterceptors(list);
            }
        };
    }
}
ログイン後にコピー

这样RestTemplate就被设置了LoadBalancerInterceptor,下面来看看整个调用过程

springcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明

整个过程有点复杂,核心就是经过拦截器LoadBalancerInterceptor,通过RibbonLoadBalancerClient发起负载均衡调用。RibbonLoadBalancerClientI组合了LoadBalancer,所以具备了负载均衡的能力,也就是我们在上一篇文章解读的ribbon原理。

图中我们没有画出真正发起http请求的过程,其默认是由SimpleClientHttpRequestFactory创建,ClientHttpRequestFactory的类图如下:

springcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明

从调用时序图上我们看到,开始我们调用的是InterceptingClientHttpRequestFactory来获取InterceptingClientHttpRequest,它们通过组合的方式集成了ClientHttpRequestFactory和拦截器,InterceptingClientHttpRequest发起调用的时候委托了其内部类InterceptingRequestExecution去处理,核心逻辑:

@Override
public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
    if (this.iterator.hasNext()) {
        ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
        return nextInterceptor.intercept(request, body, this);
    }else {
        ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod());
        for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) {
            List<String> values = entry.getValue();
            for (String value : values) {
                delegate.getHeaders().add(entry.getKey(), value);
            }
        }
        if (body.length > 0) {
            StreamUtils.copy(body, delegate.getBody());
        }
        return delegate.execute();
    }
}
ログイン後にコピー

首先会先取出拦截器集合的第一个执行,当拦截器执行完成后,会回调回来,执行else的代码,真正发起http请求,主要有两种方式实现ClientHttpRequestFactory接口:

  • 一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接

  • 一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。

RestTemplate默认是使用SimpleClientHttpRequestFactory,内部是调用jdk的HttpConnection,默认超时为-1,可以这样设置超时时间:

@Bean
@LoadBalanced
public RestTemplate restTemplate() {
    SimpleClientHttpRequestFactory factory  = new SimpleClientHttpRequestFactory();
    factory.setConnectTimeout(1000 * 2);//连接超时时间
    factory.setReadTimeout(1000 * 1);//读超时时间
    return new RestTemplate(factory);
}
ログイン後にコピー

使用HttpComponentsClientHttpRequestFactory方式可以使用连接池(推荐) ,还可以设置重试策略(具体没有研究过)

如果想开启重试机制,我们可以引入spring的retry组件

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
    <version>版本号</version>
</dependency>
ログイン後にコピー

这样springcloud-ribbon就会加重如下配置:

@Configuration
@ConditionalOnClass(RetryTemplate.class)
public static class RetryAutoConfiguration {
    @Bean
    public RetryTemplate retryTemplate() {
        RetryTemplate template =  new RetryTemplate();
        template.setThrowLastExceptionOnExhausted(true);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory() {
        return new LoadBalancedRetryPolicyFactory.NeverRetryFactory();
    }
}

@Configuration
@ConditionalOnClass(RetryTemplate.class)
public static class RetryInterceptorAutoConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public RetryLoadBalancerInterceptor ribbonInterceptor(
        LoadBalancerClient loadBalancerClient, LoadBalancerRetryProperties properties,
        LoadBalancedRetryPolicyFactory lbRetryPolicyFactory,
        LoadBalancerRequestFactory requestFactory) {
        return new RetryLoadBalancerInterceptor(loadBalancerClient, properties,
                                                lbRetryPolicyFactory, requestFactory);
    }

    @Bean
    @ConditionalOnMissingBean
    public RestTemplateCustomizer restTemplateCustomizer(
        final RetryLoadBalancerInterceptor loadBalancerInterceptor) {
        return new RestTemplateCustomizer() {
            @Override
            public void customize(RestTemplate restTemplate) {
                List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                    restTemplate.getInterceptors());
                list.add(loadBalancerInterceptor);
                restTemplate.setInterceptors(list);
            }
        };
    }
}
ログイン後にコピー
@Bean
@ConditionalOnClass(name = "org.springframework.retry.support.RetryTemplate")
@ConditionalOnMissingBean
    public LoadBalancedRetryPolicyFactory loadBalancedRetryPolicyFactory(SpringClientFactory clientFactory) {
    return new RibbonLoadBalancedRetryPolicyFactory(clientFactory);
}
ログイン後にコピー

拦截器替换成RetryLoadBalancerInterceptor了,这里集成了retry组件retryTemplate。重试策略由RetryHandler接口来配置,默认实现类DefaultLoadBalancerRetryHandler,如下为默认的配置参数

#最大的重试次数
ribbon.MaxAutoRetries=0
#最大重试server的个数
ribbon.MaxAutoRetriesNextServer=1
#是否开启任何异常都重试(默认在get请求下会重试,其他情况不会重试,除非设置为true)
ribbon.OkToRetryOnAllOperations=false
#指定重试的http状态码
ribbon.retryableStatusCodes=500,501
ログイン後にコピー

以上是对全局生效,如果加上xxx.ribbon.MaxAutoRetries=1

InterceptingHttpAccessor HttpAccessor を拡張して、インターセプトされた InterceptingClientHttpRequest を作成します。ここで、インターセプター ClientHttpRequestInterceptor が設定されます。これは、統合リボン When RestTemplate は http リクエストの呼び出しを開始します。最初にインターセプターを通過し、次に実際に http リクエストを開始します。

インターセプター ClientHttpRequestInterceptor はどのように設定されますか? LoadBalancerAutoConfiguration クラスには、次のコードがあります:

rrreee 注釈 @LoadBalanced が追加されている限り、RestTemplate が挿入されます。 Spring Retry コンポーネントを導入せずに、次の設定をロードします: rrreee

このようにして、RestTemplate が LoadBalancerInterceptor に設定されます🎜🎜springcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明🎜🎜プロセス全体は少し複雑です中心となるのは、インターセプター LoadBalancerInterceptor を通過し、RibbonLoadBalancerClient を通じて負荷分散呼び出しを開始することです。 ibbonLoadBalancerClientI は LoadBalancer を組み合わせているため、負荷分散機能が備わっています。これは、前の記事で説明したリボンの原理です。 🎜🎜図では実際に http リクエストを開始するプロセスは描いていません。デフォルトは SimpleClientHttpRequestFactory によって作成されます。ClientHttpRequestFactory のクラス図は次のとおりです。  springcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明 🎜🎜呼び出しシーケンス図から、最初に InterceptingClientHttpRequestFactory を呼び出して、 を統合した <code>InterceptingClientHttpRequest を取得したことがわかります。 ClientHttpRequestFactory は とインターセプターの組み合わせにより、 InterceptingClientHttpRequest が呼び出しを開始すると、その内部クラス InterceptingRequestExecution に処理を委託します。 🎜rrreee🎜 は最初に実行します。インターセプター コレクションの出力 最初の実行では、インターセプターが完了するとコールバックし、else コードが実行され、実際に http リクエストが開始されます。 ClientHttpRequestFactory インターフェイスを実装するには、主に 2 つの方法があります。 🎜🎜 1 つは SimpleClientHttpRequestFactory です。J2SE によって提供されるメソッド (java.net パッケージによって提供されるメソッド) を使用して、基礎となる Http リクエスト接続を作成します🎜🎜🎜 1 つの方法は、 HttpComponentsClientHttpRequestFactory メソッドでは、最下層は HttpClient を使用してリモート Http サービスにアクセスし、接続プール、証明書、その他の情報を構成できます。 🎜🎜 RestTemplate はデフォルトで SimpleClientHttpRequestFactory を使用し、デフォルトのタイムアウトは -1 です。 🎜rrreee🎜 HttpComponentsClientHttpRequestFactoryを使用します。 > メソッド. 接続プール (推奨)、再試行戦略を設定することもできます (具体的には検討していません) 🎜🎜再試行メカニズムを有効にしたい場合は、Spring の再試行コンポーネントを導入できます🎜rrreee🎜 このように、springcloud-ribbon は追加します。次の構成:🎜rrreeerrreee🎜 インターセプターは RetryLoadBalancerInterceptor に置き換えられ、再試行コンポーネント retryTemplate が統合されています。再試行戦略は、RetryHandler インターフェースによって構成されます。デフォルトの実装クラスは、DefaultLoadBalancerRetryHandler です。上記は、 の場合にグローバルに有効です。 >xxx が追加されました .ribbon.MaxAutoRetries=1これは、特定のリボン クライアントでのみ有効になります。 MaxAutoRetries と MaxAutoRetriesNextServer を併用すると、各サーバーの最大再試行回数が MaxAutoRetries=1 および MaxAutoRetriesNextServer=1 に設定されている場合、トリガーされる最大再試行回数は 4 回になります。 🎜🎜関連記事: 🎜🎜🎜🎜Java の例 - 配列からコレクションへ🎜🎜

以上がspringcloudコンポーネントのRestTemplateで統合されたリボンの詳細説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの平方根 Javaの平方根 Aug 30, 2024 pm 04:26 PM

Java の平方根のガイド。ここでは、Java で平方根がどのように機能するかを、例とそのコード実装をそれぞれ示して説明します。

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

Javaのアームストロング数 Javaのアームストロング数 Aug 30, 2024 pm 04:26 PM

Java のアームストロング番号に関するガイド。ここでは、Java でのアームストロング数の概要とコードの一部について説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

See all articles