zoukankan      html  css  js  c++  java
  • 一、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集群节点当中同步注册信息。

  • 相关阅读:
    利用VS的预生成事件获取SVN版本作为项目内部版本号
    静态构造函数到底执行了多少次?
    C#之自定义的implicit和explicit转换
    FineUI之使用SQL脚本从数据库表中生成相应的输入控件
    文件操作
    PHP中文件类型 文件属性 路径以及 文件相关的函数
    MySqli 中预处理类 stmt
    MySql 事务处理
    MySqli 执行多条SQL语句
    PHP与MySqli
  • 原文地址:https://www.cnblogs.com/lay2017/p/11918369.html
Copyright © 2011-2022 走看看