実装原理@LoadBalanced注釈およびクライアント・ロード・バランシングの深い理解

前提

このブログを読む前に、私はあなたが、より希望に精通しているとSpringCloudキットを理解してほしいその次懸念マイクロサービスの開発プラットフォーム

アウトライン

springcloudリボンクライアント・ロード・バランシングを使用するときは、RestTemplate Beanがコメントを追加@LoadBalanced、あなたは要求されたときにRestTemplate独自のクライアントの負荷が能力をバランスさせることができますすることができますが、以前のノート熟考を行っていなかっただけに対処しますこのような問題は、記録されました

@LoadBalanced

/**
 * 注释将RestTemplate bean标记为配置为使用LoadBalancerClient。
 */
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}

これは、ソースコードはで見つけることができるされLoadBalanced、マーカー注釈やマークアップ@Qualifier(ベースの自動設定メカニズム春ブーツの)を、我々はにさかのぼることができますLoadBalancerAutoConfiguration

LoadBalancerAutoConfiguration

/**
 * 功能区的自动配置(客户端负载平衡)
 */
@Configuration
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {

    @LoadBalanced
    @Autowired(required = false)
    private List<RestTemplate> restTemplates = Collections.emptyList();   //这里持有@LoadBalanced标记的RestTemplate实例

    @Autowired(required = false)
    private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();

    @Bean
    public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
            final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
        return () -> restTemplateCustomizers.ifAvailable(customizers -> {
            for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
                for (RestTemplateCustomizer customizer : customizers) {
          //为restTemplate添加定制
                    customizer.customize(restTemplate);
                }
            }
        });
    }

   // ... 

    /**
     * 以下针对classpath存在RetryTemplate.class的情况配置,先忽略
     */
    @Configuration
    @ConditionalOnClass(RetryTemplate.class)
    public static class RetryAutoConfiguration {

        @Bean
        @ConditionalOnMissingBean
        public LoadBalancedRetryFactory loadBalancedRetryFactory() {
            return new LoadBalancedRetryFactory() {
            };
        }
    }

  // ... 
}

@LoadBalancedそして、@Autowriedの組み合わせで、ここに注入されたことを意味RestTempateビーンがすべて追加されている@LoadBalanced(保持ノートラベル@LoadBalancedラベルのRestTemplate例)

自動組立のこのコードの意味が理解しやすい、すべてのRestTemplate豆のLoadBalancerInterceptorインターセプタ、およびこのインターセプタの役割を追加@LoadBalancedマークされRestTemplateCustomizerを使用してRestTempllateインターセプタの使用は、URI要求されるようにされています変換はServiceInstanceを要求すべきサービスの具体的な例を取得します。

キーは、自分自身に問う:なぜ?

  • RestTemplateの例では、収集する方法ですか?
  • 負荷分散ルールを介して特定の特定のサーバーを取得する方法は?

グリル>ソースコードを見続ける
上で見ることができ、それは次のようになりますLoadBalancerAutoConfiguration类私たちのためにプラス@LoadBalanced注釈付きの豆の追加loadBalancerInterceptorインターセプタを

LoadBalancerInterceptor

/**
* 功能区的自动配置(客户端负载平衡)。
*/
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {

    private LoadBalancerClient loadBalancer;

    private LoadBalancerRequestFactory requestFactory;

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer,
            LoadBalancerRequestFactory requestFactory) {
        this.loadBalancer = loadBalancer;
        this.requestFactory = requestFactory;
    }

    public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
        // for backwards compatibility
        this(loadBalancer, new LoadBalancerRequestFactory(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));
    }

}

我々はインターセプト法restTemplateを見て、要求された操作を実行するとフォーカスが、それがインターセプト法インターセプタを入力インターセプトされ、ロードバランサーはLoadBalancerClientの実現であります

RibbonLoadBalancerClient

    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);
    }

突然、同様の間違いを経験していると信じてここを参照してください、と

No instances available for  xxxxx

概要

  • 対応するロードバランサによるサービスIDを取得1
  • 2.ロードバランサーは、特定のサーバに応じて取得し(ここではルールをロードバランシング、特定のサービスインスタンスへのアクセス)
  • RibbonServerを作成します3。
  • 4.詳細な実行要求

ここに

注:@LoadBalanced GETリクエストによって開始され、特定の特定のサーバ負荷分散ルールの最終的なマークノートへ

ケース

/**
 * 服务注册中心配置
 *
 * @author <a href="mailto:[email protected]">iByte</a>
 * @since 1.0.1
 */
@Configuration
@EnableConfigurationProperties(ModuleMappingHelper.class)
public class DiscoveryConfig {
    @Autowired
    Environment environment;

    /**
     * DiscoveryHeaderHelper默认bean
     * @return
     */
    @Bean
    public DiscoveryHeaderHelper discoveryHeaderHelper() {
        DiscoveryHeaderHelper discoveryHeaderHelper = new DiscoveryHeaderHelper(environment);
        DiscoveryHeaderHelper.INSTANCE = discoveryHeaderHelper;
        return discoveryHeaderHelper;
    }

    /**
     * resttemplate构建
     */
    @Resource
    private RestTemplateBuilder restTemplateBuilder;

    /**
     * resttemplate请求bean,更改系统本身的builder
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = restTemplateBuilder.configure(new RestTemplate());
        //RestTemplate interceptors 远程调用请求增加头部信息处理
        restTemplate.getInterceptors().add(new RestApiHeaderInterceptor());
        //RestTemplate Set the error handler 错误处理
        restTemplate.setErrorHandler(new RestResponseErrorHandler());
        return  restTemplate;
    }

    @Bean
    public DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs() {
        DiscoveryClient.DiscoveryClientOptionalArgs discoveryClientOptionalArgs = new DiscoveryClient.DiscoveryClientOptionalArgs();
        discoveryClientOptionalArgs.setAdditionalFilters(Collections.singletonList(new DiscoveryHeaderClientFilter()));
        discoveryClientOptionalArgs.setEventListeners(Collections.singleton(new EurekaClientEventListener()));
        return discoveryClientOptionalArgs;
    }
}

ソースアドレス> DiscoveryConfig

おすすめ

転載: www.cnblogs.com/lishangzhi/p/11861026.html