前言
上一篇我们介绍了springCloud服务注册与发现机制 ,接下来我们介绍springCloud如何整合Eureka作为注册中心的。Eureka是Netflix旗下的一款实现服务注册发现的开源框架,Netflix Eureka简单理解可以包含两部分,注册中心(服务端)和 服务注册发现(客户端)。springCloud为了整合 Netflix Eureka,实现了spring-cloud-netflix-eureka-server和spring-cloud-netflix-eureka-client分别对应服务端和客户端,我们称之为 springCloud Eureka。通常我们讲的springCloud微服务架构用的注册中心一般都是使用springCloud Eureka。springCloud Eureka是基于 Netflix Eureka做了二次封装实现,包括后面我们将要分享的关于负载均衡和断路器也是基于Netflix Ribbon和Hystrix做的二次封装。服务注册与发现,我们可以简单理解为是客户端的范围,客户端怎样将自己注册到注册中心,怎样从注册中心获取服务。 而注册中心是服务端的范围,注册中心如何保存服务实例信息,如何把服务实例给到客户端,如何监听服务实例的状态等。
我们先介绍springCloud如何将eureka作为注册中心,即springCloud Eureka服务端的实现原理。
一、eureka架构图
从架构图可以看出以下几点
1、EurekaServer支持集群模式,且能够互相通信 Replicate,这是同步注册表信息(服务实例信息)。 EurekaServer可以部署在不同的区或者不同机房。
2、EurekaClient与Eureka Server通信,有register注册服务实例,renew续约,cancel服务下线,getRegistry获取注册表信息
3、EurekaClient与EurekaClient发生远程调用,这是消费者调用提供者的服务。
那么可以引出几个问题:
1、EurekaServer集群节点怎么管理,以及如何同步注册表信息?
答:EurekaServer支持 单实例和集群两种模式,且集群模式是peer to peer,不存在选主模式,这也是eureka比zk强大的地方,zk选主时集群是不可用状态。
见 PeerAwareInstanceRegistryImpl 和 EurekaServerNodes
2、EurekaServer 如何保存服务实例信息,即注册表信息
答:见 InstanceRegistry
3、EurekaClient 与 EurekaServer 之间如何通信?
答:EurekaServer见 ApplicationsResource, EurekaClient涉及客户端下一篇讲解
4、EurekaClient与EurekaClient如何通信?
答:EurekaClient涉及客户端下一篇讲解
首先说明一下,Netflix Eureka之间是通过Jersey框架通信(这是个restful协议框架,简单理解就是个类似springMVC的东西)。Netflix EurekaServer 同时也是一个EurekaClient,在 EurekaServer集群场景中,EurekaServer会将自己作为一个EurekaClient注册到 其他的Server端。
我们先从启动一个EurekaServer开始说明。
二、@EnableEurekaServer
开启EurekaServer,表明此应用为EurekaServer即注册中心。
//此注解为了import EurekaServerMarkerConfiguration,仅仅为了创建一个类似标志的 Marker bean对象@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(EurekaServerMarkerConfiguration.class)public @interface EnableEurekaServer { }@Configurationpublic class EurekaServerMarkerConfiguration { @Bean public Marker eurekaServerMarkerBean() { return new Marker(); } class Marker { }}
三、EurekaServerAutoConfiguration
位于 spring-cloud-netflix-eureka-server/META-INF/spring.factories文件
@EnableEurekaServer生成的Marker实例就是作用在这里。
此自动配置类的作用是 准备EurekaServer环境并启动。
@Configuration@Import(EurekaServerInitializerConfiguration.class) // EurekaServer初始化和启动类@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class) //Mark的Bean对象存在才会加载EurekaServerAutoConfiguration@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class })@PropertySource("classpath:/eureka/server.properties")public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter { /** * List of packages containing Jersey resources required by the Eureka server */ private static final String[] EUREKA_PACKAGES = new String[] { "com.netflix.discovery", "com.netflix.eureka" }; // netflix eureka 服务端节点 以及 eurekaClient和eurekaServer间是基于 Jersey框架实现(类似springMVC) @Autowired private ApplicationInfoManager applicationInfoManager; @Autowired private EurekaServerConfig eurekaServerConfig; // 服务端配置(eureka.server开头),springCloud实现类 EurekaServerConfigBean, Netflix实现类 DefaultEurekaServerConfig @Autowired private EurekaClientConfig eurekaClientConfig; // 客户端配置(eureka.client开头),springCloud实现类 EurekaClientConfigBean, Netflix实现类 DefaultEurekaClientConfig @Autowired private EurekaClient eurekaClient; //eureka客户端,springCloud实现类CloudEurekaClient, Netflix实现类DiscoveryClient @Autowired private InstanceRegistryProperties instanceRegistryProperties; public static final CloudJacksonJson JACKSON_JSON = new CloudJacksonJson(); @Bean public HasFeatures eurekaServerFeature() { return HasFeatures.namedFeature("Eureka Server", EurekaServerAutoConfiguration.class); } @Configuration protected static class EurekaServerConfigBeanConfiguration { @Bean //eureka.server配置 @ConditionalOnMissingBean public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) { EurekaServerConfigBean server = new EurekaServerConfigBean(); if (clientConfig.shouldRegisterWithEureka()) { // Set a sensible default if we are supposed to replicate server.setRegistrySyncRetries(5); } return server; } } @Bean // 由EurekaDashboardProperties控制,springCloudEureka后台管理页面用springMVC实现 @ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true) public EurekaController eurekaController() { return new EurekaController(this.applicationInfoManager); } static { // 使用Jackson做序列化和反序列化 CodecWrappers.registerWrapper(JACKSON_JSON); EurekaJacksonCodec.setInstance(JACKSON_JSON.getCodec()); } @Bean // 创建InstanceRegistry注册中心,springCLoud实现类InstanceRegistry, netflix实现类是PeerAwareInstanceRegistryImpl, p2p类型的注册中心,需要节点间同步信息 public PeerAwareInstanceRegistry peerAwareInstanceRegistry( ServerCodecs serverCodecs) { this.eurekaClient.getApplications(); // force initialization return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig, serverCodecs, this.eurekaClient, this.instanceRegistryProperties.getExpectedNumberOfRenewsPerMin(), this.instanceRegistryProperties.getDefaultOpenForTrafficCount()); } @Bean // PeerEurekaNodes eurekaServer节点集合管理类, springCloud实现类RefreshablePeerEurekaNodes, netflix实现类PeerEurekaNodes @ConditionalOnMissingBean public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry, ServerCodecs serverCodecs) { return new RefreshablePeerEurekaNodes(registry, this.eurekaServerConfig, this.eurekaClientConfig, serverCodecs, this.applicationInfoManager); } /** * springCloud实现类 eureka节点集合管理类, 用于在部分环境变量(eureka.client.region