• SpringCloud之Ribbon源码解析(一)--准备


    一   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

  • 相关阅读:
    Linux基础命令---arch
    JSON漫谈
    django中外键关联表的查询随笔
    <django中render_to_response的可选参数和使用方法>
    有趣的Redis:缓存被我写满了,该怎么办?
    2020全球C++及系统软件技术大会成功落下帷幕
    AWS 宣布创建 Elasticsearch 和 Kibana 分支
    Flutter开发指南之理论篇:Dart语法05(单线程模型,事件循环模型,Isolate)
    自定义注解!绝对是程序员装逼的利器!!
    Java8 Stream
  • 原文地址:https://www.cnblogs.com/juniorMa/p/14415319.html
Copyright © 2020-2023  润新知