• Spring Cloud Netflix Eureka client源码分析


    1.client端

    EurekaClient提供三个功能:

    EurekaClient API contracts are:
    * - provide the ability to get InstanceInfo(s) (in various different ways)
    * - provide the ability to get data about the local Client (known regions, own AZ etc)
    * - provide the ability to register and access the healthcheck handler for the client

    使用@EnableEurekaClient起效,其定义如下:

    /**
     * Convenience annotation for clients to enable Eureka discovery configuration
     * (specifically). Use this (optionally) in case you want discovery and know for sure that
     * it is Eureka you want. All it does is turn on discovery and let the autoconfiguration
     * find the eureka classes if they are available (i.e. you need Eureka on the classpath as
     * well).
     *
     * @author Dave Syer
     * @author Spencer Gibb
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @EnableDiscoveryClient
    public @interface EnableEurekaClient {
    
    }

    注册

    /**
     * Annotation to enable a DiscoveryClient implementation.
     * @author Spencer Gibb
     */
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @Import(EnableDiscoveryClientImportSelector.class)
    public @interface EnableDiscoveryClient {
    
        /**
         * If true, the ServiceRegistry will automatically register the local server.
         */
        boolean autoRegister() default true;
    }
    EnableDiscoveryClientImportSelector继承自SpringFactoryImportSelector,在容器启动时触发,前文已经有介绍执行路径:

    在其父类org.springframework.cloud.commons.util.SpringFactoryImportSelector
    的String[] selectImports(AnnotationMetadata metadata)方法中正是根据这个标记类判定是否加载如下定义的类。

    @Override
        public String[] selectImports(AnnotationMetadata metadata) {
            if (!isEnabled()) {
                return new String[0];
            }
            AnnotationAttributes attributes = AnnotationAttributes.fromMap(
                    metadata.getAnnotationAttributes(this.annotationClass.getName(), true));
    
            Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is "
                    + metadata.getClassName() + " annotated with @" + getSimpleName() + "?");
    
            // Find all possible auto configuration classes, filtering duplicates
            List<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader
                    .loadFactoryNames(this.annotationClass, this.beanClassLoader)));
    
            if (factories.isEmpty() && !hasDefaultFactory()) {
                throw new IllegalStateException("Annotation @" + getSimpleName()
                        + " found, but there are no implementations. Did you forget to include a starter?");
            }
    
            if (factories.size() > 1) {
                // there should only ever be one DiscoveryClient, but there might be more than
                // one factory
                log.warn("More than one implementation " + "of @" + getSimpleName()
                        + " (now relying on @Conditionals to pick one): " + factories);
            }
    
            return factories.toArray(new String[factories.size()]);
        }

    SpringFactoriesLoader调用loadFactoryNames其实加载META-INF/spring.factories下的class。

    spring-cloud-netflix-eureka-clientsrcmain esourcesMETA-INFspring.factories中配置:

     1.1.1 定义HasFeatures Bean

        @Bean
        public HasFeatures eurekaFeature() {
            return HasFeatures.namedFeature("Eureka Client", EurekaClient.class);
        }

    1.1.2 定义EurekaClientConfigBean bean

        @Bean
        @ConditionalOnMissingBean(value = EurekaClientConfig.class, search = SearchStrategy.CURRENT)
        public EurekaClientConfigBean eurekaClientConfigBean() {
            EurekaClientConfigBean client = new EurekaClientConfigBean();
            if ("bootstrap".equals(this.env.getProperty("spring.config.name"))) {
                // We don't register during bootstrap by default, but there will be another
                // chance later.
                client.setRegisterWithEureka(false);
            }
            return client;
        }

    1.1.3 定义EurekaInstanceConfigBean bean

    @Bean
        @ConditionalOnMissingBean(value = EurekaInstanceConfig.class, search = SearchStrategy.CURRENT)
        public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils) {
            EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
            instance.setNonSecurePort(this.nonSecurePort);
            instance.setInstanceId(getDefaultInstanceId(this.env));
    
            if (this.managementPort != this.nonSecurePort && this.managementPort != 0) {
                if (StringUtils.hasText(this.hostname)) {
                    instance.setHostname(this.hostname);
                }
                RelaxedPropertyResolver relaxedPropertyResolver = new RelaxedPropertyResolver(env, "eureka.instance.");
                String statusPageUrlPath = relaxedPropertyResolver.getProperty("statusPageUrlPath");
                String healthCheckUrlPath = relaxedPropertyResolver.getProperty("healthCheckUrlPath");
                if (StringUtils.hasText(statusPageUrlPath)) {
                    instance.setStatusPageUrlPath(statusPageUrlPath);
                }
                if (StringUtils.hasText(healthCheckUrlPath)) {
                    instance.setHealthCheckUrlPath(healthCheckUrlPath);
                }
                String scheme = instance.getSecurePortEnabled() ? "https" : "http";
                instance.setStatusPageUrl(scheme + "://" + instance.getHostname() + ":"
                        + this.managementPort + instance.getStatusPageUrlPath());
                instance.setHealthCheckUrl(scheme + "://" + instance.getHostname() + ":"
                        + this.managementPort + instance.getHealthCheckUrlPath());
            }
            return instance;
        }

    1.1.4 定义DiscoveryClient bean

        @Bean
        public DiscoveryClient discoveryClient(EurekaInstanceConfig config,
                EurekaClient client) {
            return new EurekaDiscoveryClient(config, client);
        }

    1.1.5 定义EurekaServiceRegistry bean

        @Bean
        public EurekaServiceRegistry eurekaServiceRegistry() {
            return new EurekaServiceRegistry();
        }

    1.1.6 定义EurekaRegistration bean

        @Bean
        @ConditionalOnBean(AutoServiceRegistrationProperties.class)
        @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
        public EurekaRegistration eurekaRegistration(EurekaClient eurekaClient, CloudEurekaInstanceConfig instanceConfig, ApplicationInfoManager applicationInfoManager) {
            return EurekaRegistration.builder(instanceConfig)
                    .with(applicationInfoManager)
                    .with(eurekaClient)
                    .with(healthCheckHandler)
                    .build();
        }

    1.1.7 定义EurekaAutoServiceRegistration bean

        @Bean
        @ConditionalOnBean(AutoServiceRegistrationProperties.class)
        @ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
        public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry registry, EurekaRegistration registration) {
            return new EurekaAutoServiceRegistration(context, registry, registration);
        }

    1.2 EurekaClientConfiguration
    1.2.1 定义
    EurekaClient bean
            @Bean(destroyMethod = "shutdown")
            @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
            public EurekaClient eurekaClient(ApplicationInfoManager manager,
                    EurekaClientConfig config) {
                return new CloudEurekaClient(manager, config, this.optionalArgs,
                        this.context);
            }

    1.2.2 定义ApplicationInfoManager bean

            @Bean
            @ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
            public ApplicationInfoManager eurekaApplicationInfoManager(
                    EurekaInstanceConfig config) {
                InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
                return new ApplicationInfoManager(config, instanceInfo);
            }

    1.3 RefreshableEurekaClientConfiguration

    1.3.1 定义EurekaClient bean

            @Bean(destroyMethod = "shutdown")
            @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
            @org.springframework.cloud.context.config.annotation.RefreshScope
            @Lazy
            public EurekaClient eurekaClient(ApplicationInfoManager manager,
                    EurekaClientConfig config, EurekaInstanceConfig instance) {
                manager.getInfo(); // force initialization
                return new CloudEurekaClient(manager, config, this.optionalArgs,
                        this.context);
            }

    1.3.2 定义ApplicationInfoManager

            @Bean
            @ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
            @org.springframework.cloud.context.config.annotation.RefreshScope
            @Lazy
            public ApplicationInfoManager eurekaApplicationInfoManager(
                    EurekaInstanceConfig config) {
                InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
                return new ApplicationInfoManager(config, instanceInfo);
            }
    参考文献:
    http://blog.csdn.net/neosmith/article/details/53131023




  • 相关阅读:
    高可用Redis服务架构分析与搭建
    Java 程序性能问题
    限流、熔断、服务降级理解
    设计模式-享元设计
    设计模式-原型设计
    java8 Stream原理
    SQL语句性能优化策略
    OAuth2和JWT
    5种常见的Docker Compose错误
    leetcode_699. 掉落的方块
  • 原文地址:https://www.cnblogs.com/davidwang456/p/6347168.html
Copyright © 2020-2023  润新知