[spring-cloud: @LoadBalanced & @LoadBalancerClient]-源码分析

发布于:2025-08-05 ⋅ 阅读:(17) ⋅ 点赞:(0)

源码

LoadBalanced

@LoadBalanced 注解用于标记 RestTemplateRestClient.BuilderWebClient.Builder Bean,使其自动集成负载均衡客户端,实现在请求时自动通过负载均衡器选择服务实例。

// LoadBalancerRestClientBuilderBeanPostProcessor
// LoadBalancerWebClientBuilderBeanPostProcessor
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {}

LoadBalancerAutoConfiguration

@AutoConfiguration
@Conditional(BlockingRestClassesPresentCondition.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
public class LoadBalancerAutoConfiguration {

	// 被标记为 @LoadBalanced 的 RestTemplate,会被注入到 restTemplates 变量中
	@LoadBalanced
	@Autowired(required = false)
	private List<RestTemplate> restTemplates = Collections.emptyList();

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

	@Bean
	public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
			ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) {
		return () -> restTemplateCustomizers.ifAvailable(customizers -> {
			for (RestTemplate restTemplate : restTemplates) {
				// LoadBalancerInterceptorConfig.restTemplateCustomizer: 
				// 	   LoadBalancerInterceptor
				// RetryInterceptorAutoConfiguration.restTemplateCustomizer: 
				// 	   RetryLoadBalancerInterceptor
				for (RestTemplateCustomizer customizer : customizers) {
					customizer.customize(restTemplate);
				}
			}
		});
	}
	
	@Bean
	@ConditionalOnMissingBean
	public LoadBalancerRequestFactory loadBalancerRequestFactory(LoadBalancerClient loadBalancerClient) {
		return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
	}
	
	// DeferringLoadBalancerInterceptorConfig
	// LoadBalancerInterceptorConfig 
	// RetryInterceptorAutoConfiguration
}
@AutoConfiguration
static class DeferringLoadBalancerInterceptorConfig {

	@Bean
	@ConditionalOnMissingBean
	public DeferringLoadBalancerInterceptor deferringLoadBalancerInterceptor(
			ObjectProvider<BlockingLoadBalancerInterceptor> loadBalancerInterceptorObjectProvider) {
		return new DeferringLoadBalancerInterceptor(loadBalancerInterceptorObjectProvider);
	}

	@Bean
	@ConditionalOnBean(DeferringLoadBalancerInterceptor.class)
	@ConditionalOnMissingBean
	LoadBalancerRestClientBuilderBeanPostProcessor lbRestClientPostProcessor(
			DeferringLoadBalancerInterceptor loadBalancerInterceptor, ApplicationContext context) {
		return new LoadBalancerRestClientBuilderBeanPostProcessor(loadBalancerInterceptor, context);
	}

}
@AutoConfiguration
@Conditional(RetryMissingOrDisabledCondition.class)
static class LoadBalancerInterceptorConfig {

	@Bean
	public LoadBalancerInterceptor loadBalancerInterceptor(LoadBalancerClient loadBalancerClient,
			LoadBalancerRequestFactory requestFactory) {
		return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
	}

	@Bean
	@ConditionalOnMissingBean
	public RestTemplateCustomizer restTemplateCustomizer(LoadBalancerInterceptor loadBalancerInterceptor) {
		return restTemplate -> {
			List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
			list.add(loadBalancerInterceptor);
			restTemplate.setInterceptors(list);
		};
	}

}

private static class RetryMissingOrDisabledCondition extends AnyNestedCondition {

	RetryMissingOrDisabledCondition() {
		super(ConfigurationPhase.REGISTER_BEAN);
	}

	@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
	static class RetryTemplateMissing {

	}

	@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", havingValue = "false")
	static class RetryDisabled {

	}

}

/**
 * Auto configuration for retry mechanism.
 */
@AutoConfiguration
@ConditionalOnClass(RetryTemplate.class)
public static class RetryAutoConfiguration {

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

}

/**
 * Auto configuration for retry intercepting mechanism.
 */
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RetryTemplate.class)
@ConditionalOnBean(ReactiveLoadBalancer.Factory.class)
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.retry.enabled", matchIfMissing = true)
public static class RetryInterceptorAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public RetryLoadBalancerInterceptor loadBalancerInterceptor(LoadBalancerClient loadBalancerClient,
			LoadBalancerRequestFactory requestFactory, LoadBalancedRetryFactory loadBalancedRetryFactory,
			ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerFactory) {
		return new RetryLoadBalancerInterceptor(loadBalancerClient, requestFactory, loadBalancedRetryFactory,
				loadBalancerFactory);
	}

	@Bean
	@ConditionalOnMissingBean
	public RestTemplateCustomizer restTemplateCustomizer(RetryLoadBalancerInterceptor loadBalancerInterceptor) {
		return restTemplate -> {
			List<ClientHttpRequestInterceptor> list = new ArrayList<>(restTemplate.getInterceptors());
			list.add(loadBalancerInterceptor);
			restTemplate.setInterceptors(list);
		};
	}
}

LoadBalancerClient

@LoadBalancerClient 注解用于配置一个负载均衡客户端,通常应用于 @Configuration 类中,结合 LoadBalancerClientFactory 可获取配置的负载均衡客户端。它允许指定客户端名称、配置类等自定义负载均衡行为。

@Configuration(proxyBeanMethods = false)
@Import(LoadBalancerClientConfigurationRegistrar.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoadBalancerClient {

	@AliasFor("name")
	String value() default "";

	@AliasFor("value")
	String name() default "";

	/**
	 * A custom <code>@Configuration</code> for the load balancer client. Can contain
	 * override <code>@Bean</code> definition for the pieces that make up the client.
	 *
	 * @see LoadBalancerClientConfiguration for the defaults
	 * @return configuration classes for the load balancer client.
	 */
	Class<?>[] configuration() default {};

}

LoadBalancerClientConfigurationRegistrar

LoadBalancerClientConfigurationRegistrar是一个 ImportBeanDefinitionRegistrar 实现,用于根据 @LoadBalancerClient 注解配置负载均衡客户端,并将相应的客户端配置注册到 Spring 上下文中。

public class LoadBalancerClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {

	private static String getClientName(Map<String, Object> client) {
		if (client == null) {
			return null;
		}
		String value = (String) client.get("value");
		if (!StringUtils.hasText(value)) {
			value = (String) client.get("name");
		}
		if (StringUtils.hasText(value)) {
			return value;
		}
		throw new IllegalStateException("Either 'name' or 'value' must be provided in @LoadBalancerClient");
	}

	private static void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
		BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(LoadBalancerClientSpecification.class);
		builder.addConstructorArgValue(name);
		builder.addConstructorArgValue(configuration);
		registry.registerBeanDefinition(name + ".LoadBalancerClientSpecification", builder.getBeanDefinition());
	}

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
		Map<String, Object> attrs = metadata.getAnnotationAttributes(LoadBalancerClients.class.getName());
		if (attrs != null && attrs.containsKey("value")) {
			AnnotationAttributes[] clients = (AnnotationAttributes[]) attrs.get("value");
			for (AnnotationAttributes client : clients) {
				registerClientConfiguration(registry, getClientName(client), client.get("configuration"));
			}
		}
		if (attrs != null && attrs.containsKey("defaultConfiguration")) {
			String name;
			if (metadata.hasEnclosingClass()) {
				name = "default." + metadata.getEnclosingClassName();
			}
			else {
				name = "default." + metadata.getClassName();
			}
			registerClientConfiguration(registry, name, attrs.get("defaultConfiguration"));
		}
		Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName());
		String name = getClientName(client);
		if (name != null) {
			registerClientConfiguration(registry, name, client.get("configuration"));
		}
	}

}

LoadBalancerClientFactory

LoadBalancerClientFactory是一个工厂类,用于根据不同服务 ID 创建子容器,管理客户端和负载均衡器的实例。

public class LoadBalancerClientFactory extends NamedContextFactory<LoadBalancerClientSpecification> implements ReactiveLoadBalancer.Factory<ServiceInstance> {

	private static final Log log = LogFactory.getLog(LoadBalancerClientFactory.class);

	public static final String NAMESPACE = "loadbalancer";

	public static final String PROPERTY_NAME = NAMESPACE + ".client.name";

	private final LoadBalancerClientsProperties properties;

	public LoadBalancerClientFactory(LoadBalancerClientsProperties properties) {
		super(LoadBalancerClientConfiguration.class, NAMESPACE, PROPERTY_NAME, new HashMap<>());
		this.properties = properties;
	}

	public LoadBalancerClientFactory(LoadBalancerClientsProperties properties, Map<String, ApplicationContextInitializer<GenericApplicationContext>> applicationContextInitializers) {
		super(LoadBalancerClientConfiguration.class, NAMESPACE, PROPERTY_NAME, applicationContextInitializers);
		this.properties = properties;
	}

	public static String getName(Environment environment) {
		return environment.getProperty(PROPERTY_NAME);
	}

	@Override
	public ReactiveLoadBalancer<ServiceInstance> getInstance(String serviceId) {
		return getInstance(serviceId, ReactorServiceInstanceLoadBalancer.class);
	}

	@Override
	public LoadBalancerProperties getProperties(String serviceId) {
		if (properties == null) {
			if (log.isWarnEnabled()) {
				log.warn("LoadBalancerClientsProperties is null. Please use the new constructor.");
			}
			return null;
		}
		if (serviceId == null || !properties.getClients().containsKey(serviceId)) {
			// no specific client properties, return default
			return properties;
		}
		// because specifics are overlayed on top of defaults, everything in `properties`,
		// unless overridden, is in `clientsProperties`
		return properties.getClients().get(serviceId);
	}

	@SuppressWarnings("unchecked")
	public LoadBalancerClientFactory withApplicationContextInitializers(Map<String, Object> applicationContextInitializers) {
		Map<String, ApplicationContextInitializer<GenericApplicationContext>> convertedInitializers = new HashMap<>();
		applicationContextInitializers.keySet()
			.forEach(contextId -> convertedInitializers.put(contextId,
					(ApplicationContextInitializer<GenericApplicationContext>) applicationContextInitializers
						.get(contextId)));
		return new LoadBalancerClientFactory(properties, convertedInitializers);
	}

}

LoadBalancerAutoConfiguration

LoadBalancerAutoConfiguration 是 Spring Cloud LoadBalancer 的自动配置类,它提供了负载均衡相关的默认 Bean 配置,包括 LoadBalancerClientFactoryLoadBalancerZoneConfigLoadBalancerEagerContextInitializer,并根据配置条件自动启用负载均衡功能。

@Configuration(proxyBeanMethods = false)
@LoadBalancerClients
@EnableConfigurationProperties({ LoadBalancerClientsProperties.class, LoadBalancerEagerLoadProperties.class })
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class, LoadBalancerBeanPostProcessorAutoConfiguration.class })
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.enabled", havingValue = "true", matchIfMissing = true)
public class LoadBalancerAutoConfiguration {

	@Bean
	@ConditionalOnMissingBean
	public LoadBalancerZoneConfig zoneConfig(Environment environment) {
		return new LoadBalancerZoneConfig(environment.getProperty("spring.cloud.loadbalancer.zone"));
	}

	@ConditionalOnMissingBean
	@Bean
	public LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsProperties properties, ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {
		LoadBalancerClientFactory clientFactory = new LoadBalancerClientFactory(properties);
		clientFactory.setConfigurations(configurations.getIfAvailable(Collections::emptyList));
		return clientFactory;
	}

	@Bean
	public LoadBalancerEagerContextInitializer loadBalancerEagerContextInitializer(
			LoadBalancerClientFactory clientFactory, LoadBalancerEagerLoadProperties properties) {
		return new LoadBalancerEagerContextInitializer(clientFactory, properties.getClients());
	}

	@Bean
	static LoadBalancerChildContextInitializer loadBalancerChildContextInitializer(
			LoadBalancerClientFactory loadBalancerClientFactory, ApplicationContext parentContext) {
		return new LoadBalancerChildContextInitializer(loadBalancerClientFactory, parentContext);
	}

}

实战

package xyz.idoly.demo;

import java.util.Arrays;
import java.util.List;

import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.web.client.RestClient;

import reactor.core.publisher.Flux;

@Configuration
@LoadBalancerClient(value = "user-services", configuration = UserServicesLoadBalancerConfiguration.class)
public class RestClientConfig {
    
    // 使用 @LoadBalanced 创建 RestClient.Builder
    @Bean
    @LoadBalanced
    public RestClient.Builder loadBalancerRestClientBuilder() {
        return RestClient.builder();
    }
}

class UserServicesLoadBalancerConfiguration {

    // 1. 创建自定义的 ReactorLoadBalancer 实现
    // @Bean
    // @Primary
    // ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) {
	// 	String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
    //     return new RandomLoadBalancer(loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class),name
    //     );
    // }


    // 2. 创建 ServiceInstanceListSupplier,用于提供服务实例列表
    @Bean
    public ServiceInstanceListSupplier serviceInstanceListSupplier(Environment environment) {
        // 返回自定义的服务实例列表提供者
        return new UserServicesServiceInstanceListSupplier("user-services");
    }

    // 3. 自定义的 ServiceInstanceListSupplier 实现
    static class UserServicesServiceInstanceListSupplier implements ServiceInstanceListSupplier {

        private final String serviceId;

        UserServicesServiceInstanceListSupplier(String serviceId) {
            this.serviceId = serviceId;
        }

        @Override
        public String getServiceId() {
            return serviceId;
        }

        @Override
        public Flux<List<ServiceInstance>> get() {
            // 模拟返回多个服务实例
            return Flux.just(Arrays.asList(
                    new DefaultServiceInstance(serviceId + "1", serviceId, "localhost", 8090, false),
                    new DefaultServiceInstance(serviceId + "2", serviceId, "localhost", 9090, false),
                    new DefaultServiceInstance(serviceId + "3", serviceId, "localhost", 9091, false)
            ));
        }
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到