一般 Eureka 在使用的时候大家都是使用 Spring Boot 的 start 方式来实现,这种方式比较简单易用,但是隐藏了很多的实现细节,其实未必是很好的事情。那么 Eureka 是如何实现的呢?下面我们来探究一下。
下载完 eureka 的源码之后,我们来看一下结构,其中有一个子模块 eureka-server,这个模块是一个 web 项目。我们看一下 web.xml ,发现里面配置了一个 Listener,这个 Listener 是 Eureka core 里的 EurekaBootStrap。这个类就是 eureka Server 能工具的启动类,居然是通过 tomcat 的 Listener 机制实现的,如果是 Jetty 是不是该设置 handler ?不了解 jetty,所以不多说了。我们来看一下这个类都做了哪些事。
这个类的实现其实比较简单,主要方法在 contextInitialized 方法中,首先调用 initEurekaEnvironment 来初始化 Eureka 环境。这个方法里面使用了 archaius-core 里面的 ConfigurationManager 类,这个类就是专门用来加载相应的配置的。
ConfigurationManager 这个类使用了 Apache Commons Configuration 这个 jar 包来进行系统级统一配置的管理。我们可以先查看 getConfigInstance 是如何生成 AbstractConfiguration, 里面使用了 ConcurrentCompositeConfiguration,这个类会组合各种 Configuration,当你查找对应的属性的时候,它会逐个 Configuration 地查找,直到查到你要的属性。这个是 archaius-core 里面的具体实现,我们的配置也是提供了类似的定制化的初始数据配置,但是我们在使用 eureka 系统的时候基本上没有配置什么初始化属性,所以都是使用的默认属性。当然如果想实现自己的定制初始化配置,可以使用 archaius-core 里面给我们的配置方式进行配置。initEurekaEnvironment 中需要读取 eureka.datacenter 和 archaius.deployment.environment 来配置。默认分别是 default 和 test。
OK,以上就是设置 Environment 的过程,这其实是因为使用了 archaius 的缘故,其实也没啥。下面的 initEurekaServerContext 才是重头戏。它首先新建了 DefaultEurekaServerConfig,然后使用 Xstream 这个第三方库,实例化了 JSON 和 XML 的解析器。然后初始化自己的 JSONXstream 和 XmlXStream,这两个类都是继承 XStream 的,里面主要是利用了 XStream 提供的 Converts 外接自定义的方式进行实现的,在这两个类中向 XStream 注册了很多在 Converts 类中定义的各种 Converts,然后触发 XStream 的注解处理器,当然这个注解的处理器就是上面我们定义的那些 Converts,中间是通过注解的类进行的沟通,而且每种注解的意义都是预设的,这个以后研究说明,这里就简单介绍一下;我们可以看一下 XMLXStream 类的构造方法就明白了。
public XmlXStream() {
super(new DomDriver(null, initializeNameCoder()));
// 注册自己的 Converters
registerConverter(new Converters.ApplicationConverter());
registerConverter(new Converters.ApplicationsConverter());
registerConverter(new Converters.DataCenterInfoConverter());
registerConverter(new Converters.InstanceInfoConverter());
registerConverter(new Converters.LeaseInfoConverter());
registerConverter(new Converters.MetadataConverter());
setMode(XStream.NO_REFERENCES);
// 触发注解实现,利用上面注册的 Converts 处理下面的注解。
processAnnotations(new Class[]{InstanceInfo.class, Application.class, Applications.class});
}
接着创建 ServerCodec 实例,ServerCodec 是封装了,JSON 和 XML 解析的实现,类内部聚合了 CodecWrapper,CodecWrapper 是用来封装具体的 JSON 和 XML 的解析。这个可以看到具体的实现:
public class DefaultServerCodecs implements ServerCodecs {
protected final CodecWrapper fullJsonCodec;
protected final CodecWrapper compactJsonCodec;
protected final CodecWrapper fullXmlCodec;
protected final CodecWrapper compactXmlCodec;
......
}
关于 CodecWrapper 其实就是封装统一的 decode 和 encode 函数,这个可以自行去看它的继承机构,具体的实现我们也不用去探究了。主要是利用了 XStream 这个包里面的工具。
我们可以看一下 EurekaServerConfig:Build 内部类,我们可以发现,JSON 和 XML 的解析实现,我们是可以在系统配置来指定的。
/**
* 原来在 EurekaServerConfig 中,我们可以指定 JSON 和 XML 的解析类
* @param config
* @return
*/
public Builder withEurekaServerConfig(EurekaServerConfig config) {
fullJsonCodec = CodecWrappers.getCodec(config.getJsonCodecName());
fullXmlCodec = CodecWrappers.getCodec(config.getXmlCodecName());
return this;
}
未完待续