一、eureka服务端自动配置

所有文章

https://www.cnblogs.com/lay2017/p/11908715.html

正文

@EnableEurekaServer开关

eureka是一个c/s架构的服务治理框架,springcloud将其集成用作服务治理。springcloud使用eureka比较简单,只需要引入依赖以后添加一个@EnableEurekaServer注解即可,如

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }

}

@EnableEurekaServer又有什么魔力呢?为什么它能够开关EurekaServer?为此,我们打开@EnableEurekaServer注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {

}

可以看到,@EnableEurekaServer的@Import注解导入了一个EurekaServerMarkerConfiguration类。所以,开启@EnableEurekaServer注解也就是导入该类。

那么,EurekaServerMarkerConfiguration这个配置类又做了啥?

@Configuration
public class EurekaServerMarkerConfiguration {

    @Bean
    public Marker eurekaServerMarkerBean() {
        return new Marker();
    }

    class Marker {

    }
}

可以看到,这里只是把一个空的Marker类变成了spring中的Bean。而Marker本身什么功能都没有实现。顾名思义,我们可以这样猜测一下:@EnableEurekaServer注解就是将Marker配置为Bean,而Marker作为Bean的存在,将会触发自动配置,从而达到了一个开关的效果。

EurekaServerAutoConfiguration自动配置类

我们再打开EurekaServerAutoConfiguration这个自动配置类

@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
        InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
    // ......
}

首先值得注意的是@ConditionalOnBean这个注解,它将判断EurekaServerMarkerConfiguration.Marker这个Bean是否存在。如果存在才会解析这个自动配置类,从而呼应了@EnableEurekaServer这个注解的功能。

@EnableConfigurationProperties注解和@PropertySource注解都加载了一些键值对的属性。

@Import导入了一个初始化类EurekaServerInitializerConfiguration(后面再看它)

EurekaServerAutoConfiguration作为自动配置类,我们看看它主要配置了哪些东西(有所忽略)

看板

服务治理少不了需要一个DashBoard来可视化监控,EurekaController基于springmvc提供DashBoard相关的功能。

@Bean
@ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled",
        matchIfMissing = true)
public EurekaController eurekaController() {
    return new EurekaController(this.applicationInfoManager);
}

发现注册

发现注册作为主要的核心功能,也是必不可少的

@Bean
public PeerAwareInstanceRegistry peerAwareInstanceRegistry(
        ServerCodecs serverCodecs) {
    this.eurekaClient.getApplications(); // force initialization
    return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig,
            serverCodecs, this.eurekaClient,
            this.instanceRegistryProperties.getExpectedNumberOfClientsSendingRenews(),
            this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
}

启动引导

@Bean
public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
        EurekaServerContext serverContext) {
    return new EurekaServerBootstrap(this.applicationInfoManager,
            this.eurekaClientConfig, this.eurekaServerConfig, registry,
            serverContext);
}

Jersey提供rpc调用

jersey是一个restful风格的基于http的rpc调用框架,eureka使用它来为客户端提供远程服务。

@Bean
public javax.ws.rs.core.Application jerseyApplication(Environment environment,
        ResourceLoader resourceLoader) {

    ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
            false, environment);

    // Filter to include only classes that have a particular annotation.
    //
    provider.addIncludeFilter(new AnnotationTypeFilter(Path.class));
    provider.addIncludeFilter(new AnnotationTypeFilter(Provider.class));

    // Find classes in Eureka packages (or subpackages)
    //
    Set<Class<?>> classes = new HashSet<>();
    for (String basePackage : EUREKA_PACKAGES) {
        Set<BeanDefinition> beans = provider.findCandidateComponents(basePackage);
        for (BeanDefinition bd : beans) {
            Class<?> cls = ClassUtils.resolveClassName(bd.getBeanClassName(),
                    resourceLoader.getClassLoader());
            classes.add(cls);
        }
    }

    // Construct the Jersey ResourceConfig
    Map<String, Object> propsAndFeatures = new HashMap<>();
    propsAndFeatures.put(
            // Skip static content used by the webapp
            ServletContainer.PROPERTY_WEB_PAGE_CONTENT_REGEX,
            EurekaConstants.DEFAULT_PREFIX + "/(fonts|images|css|js)/.*");

    DefaultResourceConfig rc = new DefaultResourceConfig(classes);
    rc.setPropertiesAndFeatures(propsAndFeatures);

    return rc;
}

这里将会扫描Resource,并添加到ResourceConfig当中。

EurekaServerInitializerConfiguration初始化

再回过头来,看看@EnableEurekaServer注解导入的EurekaServerInitializerConfiguration类。

@Configuration
public class EurekaServerInitializerConfiguration implements ServletContextAware, SmartLifecycle, Ordered {
    // ...

    @Override
    public void start() {
        new Thread(() -> {
            try {
                eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);

                publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
                EurekaServerInitializerConfiguration.this.running = true;
                publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
            } catch (Exception ex) {
                //
            }
        }).start();
    }

}

初始化过程调用了EurekaServerBootstrap的contextInitialized方法,我们跟进看看

public void contextInitialized(ServletContext context) {
    try {
        initEurekaEnvironment();
        initEurekaServerContext();

        context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
    }
    catch (Throwable e) {
        log.error("Cannot bootstrap eureka server :", e);
        throw new RuntimeException("Cannot bootstrap eureka server :", e);
    }
}

这里初始化了EurekaEnvironment和EurekaServerContext,EurekaEnvironment无非就是设置了各种配置之类的东西。我们打开initEurekaServerContext看看

protected void initEurekaServerContext() throws Exception {
    // ......

    // Copy registry from neighboring eureka node
    int registryCount = this.registry.syncUp();
    this.registry.openForTraffic(this.applicationInfoManager, registryCount);

    // Register all monitoring statistics.
    EurekaMonitors.registerAllStats();
}

这里主要做了两件事:

1)从相邻的集群节点当中同步注册信息

2)注册一个统计器

总结

@EnableEurekaServer注解开启了EurekaServerAutoConfiguration这个配置类的解析,EurekaServerAutoConfiguration这个配置了主要准备了看板、注册发现、启动引导、Jersey等,EurekaServerInitializerConfigration将会触发启动引导,引导过程会从其它Eureka集群节点当中同步注册信息。

猜你喜欢

转载自www.cnblogs.com/lay2017/p/11918369.html