Eureka Server源码解析(一)

135 阅读2分钟

前言

源码解析基于Hoxton.SR1版本

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
    
<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
</dependencies>

1、摘要

  • 服务注册
  • 服务发现
  • 服务下架 client--主动 服务下架和服务剔除最终调用的是同一个方法 server集群间会进行同步
  • 服务剔除 client--被动(eureka server维持一个定时任务扫描服务注册表,判断服务心跳续约是否过期) eureka server判断心跳过期 server集群间不进行同步
  • 心跳续约
  • 自我保护机制
  • 缓存机制(包含客户端缓存和服务端缓存)
  • 集群同步 (PeerAwareInstanceRegistryImpl#renew负责所有eureka server的集群同步)

eureka server也是一个mvc架构,controller层使用jersey框架实现(本文只关注请求处理逻辑)

注册中心需要与客户端进行交互 接受请求 返回响应 -- mvc架构(不是springmvc(基于servlet),而是通过jersey(基于过滤器)实现的)

2、eureka server自动配置原理

springboot项目使用注册中心

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}

查看@EnableEurekaServer的类定义

@Import({EurekaServerMarkerConfiguration.class})
    public @interface EnableEurekaServer {
}

@EnableEurekaServer给容器里导入了一个bean == EurekaServerMarkerConfiguration

public class EurekaServerMarkerConfiguration {

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

EurekaServerMarkerConfiguration给容器里导入了一个Marker(标记) bean 这个Marker的作用就是一个标记 标记用户有没有使用@EnableEurekaServer这个注解

在spring-cloud-netflix-eureka-server的META-INF/spring.factories中 导入了EurekaServerAutoConfiguration自动配置类

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 org.springframework.cloud.netflix.eureka.server.EurekaServerAutoConfiguration
@Configuration(proxyBeanMethods = false)
//导入配置类
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)  //当前配置类是否生效
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
      InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration implements WebMvcConfigurer {
    //省略部分代码
 
    //jersey框架基于过滤器 注册过滤器到容器中
    @Bean
	public FilterRegistrationBean<?> jerseyFilterRegistration(
			javax.ws.rs.core.Application eurekaJerseyApp) {
		FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<Filter>();
		bean.setFilter(new ServletContainer(eurekaJerseyApp));
		bean.setOrder(Ordered.LOWEST_PRECEDENCE);
		bean.setUrlPatterns(
				Collections.singletonList(EurekaConstants.DEFAULT_PREFIX + "/*"));

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

		ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
				false, environment);

		/**
		 *  includeFilters:允许过滤的条件 指定需要扫描的内容(此处内容是Component注解)
		 *
		 *  代表只有被includeFilters内匹配的注解才可以被扫描解析
		 */
		provider.addIncludeFilter(new AnnotationTypeFilter(Path.class));
		provider.addIncludeFilter(new AnnotationTypeFilter(Provider.class));

		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;
	}



eureka server自动配置原理.png

3、整体架构

springcloud整合netflix的eureka server模块,在业务逻辑(服务注册、心跳续约、服务下架...)处理上基于责任链模式。

InstanceRegistry extends PeerAwareInstanceRegistryImpl extends AbstractInstanceRegistry 责任链模式

  • InstanceRegistry spring cloud提供的 用来整合netflix eureka server,主要是发布事件
EurekaInstanceRegisteredEvent:注册事件
EurekaInstanceRenewedEvent:心跳续约时间
EurekaInstanceCanceledEvent:服务下架和服务剔除事件

我们可以在spring应用中编写监听器 监听这些事件

  • PeerAwareInstanceRegistryImpl

netflix提供的 用来的做集群同步操作的

  • AbstractInstanceRegistry

netflix提供的 真正用来实现服务注册 心跳续约 的业务类