一 RibbonAutoConfiguration
@Configuration @Conditional(RibbonAutoConfiguration.RibbonClassesConditions.class) @RibbonClients @AutoConfigureAfter( name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration") @AutoConfigureBefore({ LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class }) @EnableConfigurationProperties({ RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class }) public class RibbonAutoConfiguration { @Autowired(required = false) private List<RibbonClientSpecification> configurations = new ArrayList<>(); @Autowired private RibbonEagerLoadProperties ribbonEagerLoadProperties; @Bean public HasFeatures ribbonFeature() { return HasFeatures.namedFeature("Ribbon", Ribbon.class); } @Bean public SpringClientFactory springClientFactory() { SpringClientFactory factory = new SpringClientFactory(); factory.setConfigurations(this.configurations); return factory; } @Bean @ConditionalOnMissingBean(LoadBalancerClient.class) public LoadBalancerClient loadBalancerClient() { return new RibbonLoadBalancerClient(springClientFactory()); }
RibbonLoadBalancerClient继承自LoadBalancerClient接口,是负载均衡客户端,也是负载均衡策略的调用方。
二 LoadBalancerInterceptorConfig
LoadBalancerInterceptorConfig 是一个静态内部类,主类是 LoadBalancerAutoConfiguration
@Configuration(proxyBeanMethods = false) @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 restTemplate -> { List<ClientHttpRequestInterceptor> list = new ArrayList<>( restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); restTemplate.setInterceptors(list); }; } }
生成一个LoadBalancerInterceptor,该类主要是负责拦截请求,并把请求转发出去,它有两个成员
LoadBalancerClient
LoadBalancerRequestFactory
这两个都是上一步中的两个bean
RestTemplateCustomizer负责把拦截器set到RestTemplate中
三 LoadBalancerAutoConfiguration
@Configuration @ConditionalOnClass(RestTemplate.class) @ConditionalOnBean(LoadBalancerClient.class) @EnableConfigurationProperties(LoadBalancerRetryProperties.class) public class LoadBalancerAutoConfiguration { // 略 @Bean public SmartInitializingSingleton loadBalancedRestTemplateInitializer( final List<RestTemplateCustomizer> customizers) { return new SmartInitializingSingleton() { @Override public void afterSingletonsInstantiated() { for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) { for (RestTemplateCustomizer customizer : customizers) { customizer.customize(restTemplate); } } } }; }
这里值得琢磨一下,首先看这个 loadBalancedRestTemplateInitializer方法中实现的逻辑就是调用上一节中的RestTemplateCustomizer的 customize 方法。
那么 SmartInitializingSingleton 又是在哪里被调用的呢?
这就得回到Spring中了
DefaultListableBeanFactory. preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException { if (logger.isTraceEnabled()) { logger.trace("Pre-instantiating singletons in " + this); } // Iterate over a copy to allow for init methods which in turn register new bean definitions. // While this may not be part of the regular factory bootstrap, it does otherwise work fine. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); // Trigger initialization of all non-lazy singleton beans... for (String beanName : beanNames) { RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { if (isFactoryBean(beanName)) { Object bean = getBean(FACTORY_BEAN_PREFIX + beanName); if (bean instanceof FactoryBean) { final FactoryBean<?> factory = (FactoryBean<?>) bean; boolean isEagerInit; if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) { isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit, getAccessControlContext()); } else { isEagerInit = (factory instanceof SmartFactoryBean && ((SmartFactoryBean<?>) factory).isEagerInit()); } if (isEagerInit) { getBean(beanName); } } } else { getBean(beanName); } } } // Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged((PrivilegedAction<Object>) () -> { smartSingleton.afterSingletonsInstantiated(); return null; }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } } }
那么preInstantiateSingletons又是在哪里调用的呢
有请著名的AbstractApplicationContext
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); }
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Register a default embedded value resolver if no bean post-processor // (such as a PropertyPlaceholderConfigurer bean) registered any before: // at this point, primarily for resolution in annotation attribute values. if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons(); }
四 RibbonClientConfiguration
org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
@Bean @ConditionalOnMissingBean public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) { if (this.propertiesFactory.isSet(ILoadBalancer.class, name)) { return this.propertiesFactory.get(ILoadBalancer.class, config, name); } return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList, serverListFilter, serverListUpdater); }
public interface ILoadBalancer { /** * Initial list of servers. * This API also serves to add additional ones at a later time * The same logical server (host:port) could essentially be added multiple times * (helpful in cases where you want to give more "weightage" perhaps ..) * * @param newServers new servers to add */ public void addServers(List<Server> newServers); /** * Choose a server from load balancer. * * @param key An object that the load balancer may use to determine which server to return. null if * the load balancer does not use this parameter. * @return server chosen */ public Server chooseServer(Object key); /** * To be called by the clients of the load balancer to notify that a Server is down * else, the LB will think its still Alive until the next Ping cycle - potentially * (assuming that the LB Impl does a ping) * * @param server Server to mark as down */ public void markServerDown(Server server); /** * @deprecated 2016-01-20 This method is deprecated in favor of the * cleaner {@link #getReachableServers} (equivalent to availableOnly=true) * and {@link #getAllServers} API (equivalent to availableOnly=false). * * Get the current list of servers. * * @param availableOnly if true, only live and available servers should be returned */ @Deprecated public List<Server> getServerList(boolean availableOnly); /** * @return Only the servers that are up and reachable. */ public List<Server> getReachableServers(); /** * @return All known servers, both reachable and unreachable. */ public List<Server> getAllServers(); }
ILoadBalancer 就是进行负载均衡的实际执行者,其实现类就是ZoneAwareLoadBalancer,主要功能就是负责选择server发送请求的
到此准备工作已经做好了,主角们都有
SpringClientFactory 、
LoadBalancerClient
LoadBalancerInterceptor
RestTemplateCustomizer
ZoneAwareLoadBalancer