目录
SpringCloud-Eureka
整合项目
https://github.com/spring-cloud/spring-cloud-netflix
spring-cloud-netflix-eureka-server
spring-cloud-netflix-eureka-client
SpringCloud 集成Netflix的组件说明文档地址
Netflix的Wikihttps://github.com/Netflix/eureka/wiki
Eureka架构图
关键概念
Region(区域)
- 属于AWS概念,主要为了给基础设施服务划分区域,实现高可用,提高网络传输速度。
Zone(可用区)
- 属于AWS概念,为了实现高可用,在每个Region中可以有多个Zone,且每个Zone都是独立的,一个可用区出问题不会影响到其他可用区,这样也可以实现网络的低延迟。上图中的us-east-1c表示的就是一个可用区。
租约(lease)
- Eureka Server 用于管理Erueka Client(主要管理Application Service)
- 客户端通过每隔30秒,向Eureka Server发送心跳来续约,如果Eureka Server在90秒内没有收到客户端的续约,则会将该客户端从注册表里删除。
Eureka Server
- 提供服务的注册和发现的功能
- Register 提供服务注册功能
- Renew 提供服务续租约(lease)功能
- Cancel 提供服务注销功能
- Get Registry 提供注册表获取功能,即服务发现
Application Service
- 服务提供者。
Application Client
- 服务消费者,每个client会缓存注册表的信息,这样可以再Eureka Server不可用的时候,不影响服务消费者同服务提供者的交互,同ZK的主要区别,即实现CAP中的AP。
SpringCloud启动Eureka 的过程:
EnableEurekaServer注解
SpringCloud通过注解EnableEurekaServer启动eureka服务,其包含了EnableDiscoveryClient。
SpringCloud与jersey Rest框架
eureka 基于jersey实现Rest服务,因此,如果不想采用jersey,则只需要过滤相关包的依赖即可,SpringCLoud则会采用RestTemplate来发送Rest请求。这也说明了eureka其是基于Servlet实现的。
jersey启动
SpringCloud在容器启动的时候,动态添加过滤器servletContainer 并拦截/eureka/* 的url。在该过滤器初始化的时候便加载了com.sun.jersey.spi.container.servlet.ServletContainer 该filter包含的classes有:作为jersey的WebComponent的ResourceConfig
- com.netflix.eureka.resources.ASGResource
- com.netflix.discovery.provider.DiscoveryJerseyProvider
- com.netflix.eureka.resources.ApplicationsResource
- com.netflix.eureka.resources.StatusResource
- com.netflix.eureka.resources.PeerReplicationResource
- com.netflix.eureka.resources.VIPResource
- com.netflix.eureka.resources.ServerInfoResource
- com.netflix.eureka.resources.InstancesResource
- com.netflix.eureka.resources.SecureVIPResource
再通过WebApplicationProvider初始化jersey服务。具体实现为WebApplicationImpl._initiate方法。
WebApplicationFactory
public static WebApplication createWebApplication() throws ContainerException {
for (WebApplicationProvider wap : ServiceFinder.find(WebApplicationProvider.class)) {
// Use the first provider found
// 创建jersey服务
return wap.createWebApplication();
}
throw new ContainerException("No WebApplication provider is present");
}
再由com.sun.jersey.core.spi.component.ProviderFactory 通过反射实例化com.netflix.discovery.provider.DiscoveryJerseyProvider负责将对象实例化和反序列化发送到eureka服务器
private ComponentProvider __getComponentProvider(Class c) {
try {
ComponentInjector ci = new ComponentInjector(this.ipc, c);
ComponentConstructor cc = new ComponentConstructor(this.ipc, c, ci);
// 实例化Provider
Object o = cc.getInstance();
return new ProviderFactory.SingletonComponentProvider(ci, o);
} catch (NoClassDefFoundError var5) {
LOGGER.log(Level.CONFIG, "A dependent class, " + var5.getLocalizedMessage() + ", of the component " + c + " is not found." + " The component is ignored.");
return null;
} catch (InvocationTargetException var6) {
if(var6.getCause() instanceof NoClassDefFoundError) {
NoClassDefFoundError ncdf = (NoClassDefFoundError)var6.getCause();
LOGGER.log(Level.CONFIG, "A dependent class, " + ncdf.getLocalizedMessage() + ", of the component " + c + " is not found." + " The component is ignored.");
return null;
} else {
LOGGER.log(Level.SEVERE, "The provider class, " + c + ", could not be instantiated. Processing will continue but the class will not be utilized", var6.getTargetException());
return null;
}
} catch (Exception var7) {
LOGGER.log(Level.SEVERE, "The provider class, " + c + ", could not be instantiated. Processing will continue but the class will not be utilized", var7);
return null;
}
}
配置信息加载
ConfigurationClassEnhancer
- 负责注解Configuration和注解Bean等的实例化,如:
- WebMvcConfigurationSupport根据classpath中是否存在gson、jackson等来
- ArchaiusAutoConfiguration加载archaius配置信息
protected void configureArchaius(ConfigurableEnvironmentConfiguration envConfig) {
if (initialized.compareAndSet(false, true)) {
// 获取appName 没有配置则用默认
String appName = this.env.getProperty("spring.application.name");
if (appName == null) {
appName = "application";
log.warn("No spring.application.name found, defaulting to 'application'");
}
// 后面代码省略...
}
}
DefaultListableBeanFactory基于代理实例化eureka组件等,如配置信息,EurekaClient
EurekaClientAutoConfiguration InstanceInfo EurekaClient
EurekaClientConfigBean
SpringCloud对EurekaClient的配置项
EurekaClientAutoConfiguration设置向eureka server或者向其他服务发现组件 注册需要的信息即InstanceInfo,此处为SpringCloud做的适配。
@ProvidedBy(EurekaConfigBasedInstanceInfoProvider.class)
@Serializer("com.netflix.discovery.converters.EntityBodyConverter")
@XStreamAlias("instance")// xml格式的节点
@JsonRootName("instance")// json格式的节点
public class InstanceInfo {
//代码省略...}
@Bean
@ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public ApplicationInfoManager eurekaApplicationInfoManager(EurekaInstanceConfig config) {
// 实例化向注册表注册所需要的信息,如eureka主页地址、本机ip、appName等
InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
return new ApplicationInfoManager(config, instanceInfo);
}
EurekaClientAutoConfiguration实例化EurekaClient,设置配置信息,PropertyBasedClientConfigConstants为配置变量名,以及一些默认值,实现类为DiscoveryClient
- EurekaClientAutoConfiguration 源码
@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);
}
也会通过EurekaAutoServiceRegistration,将服务自动注册到SpringCloud的服务发现注册框架,定时进行健康检查。