文章目录
1.1 Eureka 单节点搭建
-
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> 有的教程中还引入spring-boot-starter-web,其实不用。因为上面的依赖已经包含了它。在pom中点此依赖进去,一共点4次spring-cloud-netflix-eureka-server,发现web的依赖。
-
application.yml
eureka: client: #是否将自己注册到Eureka Server,默认为true,由于当前就是server,故而设置成false,表明该服务不会向eureka注册自己的信息 register-with-eureka: false #是否从eureka server获取注册信息,由于单节点,不需要同步其他节点数据,用false fetch-registry: false #设置服务注册中心的URL,用于client和server端交流 service-url: defaultZone: http://root:root@eureka-7901:7901/eureka/
-
代码
启动类上添加此注解标识该服务为配置中心 @EnableEurekaServer
-
PS:Eureka会暴露一些端点。端点用于Eureka Client注册自身,获取注册表,发送心跳。
-
简单看一下eureka server控制台,实例信息区,运行环境信息区,Eureka Server自身信息区。
1.2 整体介绍
- 背景:在传统应用中,组件之间的调用,通过有规范的约束的接口来实现,从而实现不同模块间良好的协作。但是被拆分成微服务后,每个微服务实例的网络地址都可能动态变化,数量也会变化,使得原来硬编码的地址失去了作用。需要一个中心化的组件来进行服务的登记和管理。
- 概念:实现服务治理,即管理所有的服务信息和状态。
注册中心相当于买票乘车,只看有没有票(有没有服务),有就去买票(获取注册列表),然后乘车(调用)。不必关心有多少火车在运行。
-
注册中心好处:不用关心有多少提供方。
-
注册中心有哪些:Eureka,Nacos,Consul,Zookeeper等。
-
服务注册与发现包括两部分,一个是服务器端,另一个是客户端。
Server是一个公共服务,为Client提供服务注册和发现的功能,维护注册到自身的Client的相关信息,同时提供接口给Client获取注册表中其他服务的信息,使得动态变化的Client能够进行服务间的相互调用。
Client将自己的服务信息通过一定的方式登记到Server上,并在正常范围内维护自己信息一致性,方便其他服务发现自己,同时可以通过Server获取到自己依赖的其他服务信息,完成服务调用,还内置了负载均衡器,用来进行基本的负载均衡。
-
我们课程的Spring Cloud是用Eureka作为服务注册中心。
-
Eureka:是一个RESTful风格的服务,是一个用于服务发现和注册的基础组件,是搭建Spring Cloud微服务的前提之一,它屏蔽了Server和client的交互细节,使得开发者将精力放到业务上。
-
serverA从serverB同步信息,则serverB是serverA的peer。
-
上面例子中如果service-url为空,且register-with-eureka,fetch-registry为true,则会报错,Cannot execute request on any known server,因为server同时也是一个client,他会尝试注册自己,所以要有一个注册中心url去注册。
-
Netflix开源的组件。包括server和client两部分。
https://github.com/Netflix/Eureka
1.3 注册中心和微服务间的关系
《服务注册与发现关系图》
1.3.1 client功能
- 注册:每个微服务启动时,将自己的网络地址等信息注册到注册中心,注册中心会存储(内存中)这些信息。
- 获取服务注册表:服务消费者从注册中心,查询服务提供者的网络地址,并使用该地址调用服务提供者,为了避免每次都查注册表信息,所以client会定时去server拉取注册表信息到缓存到client本地。
- 心跳:各个微服务与注册中心通过某种机制(心跳)通信,若注册中心长时间和服务间没有通信,就会注销该实例。
- 调用:实际的服务调用,通过注册表,解析服务名和具体地址的对应关系,找到具体服务的地址,进行实际调用。
1.3.2 server注册中心功能
-
服务注册表:记录各个微服务信息,例如服务名称,ip,端口等。
注册表提供 查询API(查询可用的微服务实例)和管理API(用于服务的注册和注销)。
-
服务注册与发现:注册:将微服务信息注册到注册中心。发现:查询可用微服务列表及其网络地址。
-
服务检查:定时检测已注册的服务,如发现某实例长时间无法访问,就从注册表中移除。
组件:Eureka , Consul , ZooKeeper,nacos等。
1.4 服务注册
例子:api-listen-order
- pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- application.yml
#注册中心
eureka:
client:
#设置服务注册中心的URL
service-url:
defaultZone: http://root:root@localhost:7900/eureka/
ps:不想注册,设置成false即可,实例演示结果:注册中心没有实例信息。找控制台204信息也没有找到。
spring:
cloud:
service-registry:
auto-registration:
enabled: false
注册成功:
DiscoveryClient_API-LISTEN-ORDER/api-listen-order:30.136.133.9:port - registration status: 204
PS:
Eureka Server与Eureka Client之间的联系主要通过心跳的方式实现。心跳(Heartbeat)即Eureka Client定时向Eureka Server汇报本服务实例当前的状态,维护本服务实例在注册表中租约的有效性。
Eureka Client将定时从Eureka Server中拉取注册表中的信息,并将这些信息缓存到本地,用于服务发现。
1.5 Eureka高可用
高可用:可以通过运行多个Eureka server实例并相互注册的方式实现。Server节点之间会彼此增量地同步信息,从而确保节点中数据一致。
- 注册中心改造
application.yml
参考:#高可用2个节点的yml
#高可用2个节点
#应用名称及验证账号
spring:
application:
name: eureka
security:
user:
name: root
password: root
logging:
level:
root: debug
---
spring:
profiles: 7901
server:
port: 7901
eureka:
instance:
hostname: eureka-7901
client:
#设置服务注册中心的URL
service-url:
defaultZone: http://root:root@eureka-7902:7902/eureka/
---
spring:
profiles: 7902
server:
port: 7902
eureka:
instance:
hostname: eureka-7902
client:
#设置服务注册中心的URL
service-url:
defaultZone: http://root:root@eureka-7901:7901/eureka/
—将配置文件分成2段,每段指定spring.profiles。第一段没有指定,所以共用。
-
服务注册改造
api-listen-order
eureka:
client:
#设置服务注册中心的URL
service-url:
defaultZone: http://root:root@eureka-7901:7901/eureka/,http://root:root@eureka-7902:7902/eureka/
写一个地址也行(但是server得互相注册),EurekaServer会自动同步,但为了避免极端情况,还是写多个。
集群PS:
集群中各个server会从其他server同步注册表信息。
1.6 Eureka 端点
看官网:
https://github.com/Netflix/eureka/wiki/Eureka-REST-operations
body:
<instance>
<instanceId>instanceid-2019</instanceId>
<hostName>eureka-7900</hostName>
<app>EUREKA-custom</app>
<ipAddr>127.0.0.1</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">1900</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
</instance>
地址:localhost:7900/eureka/apps/{applicaitonName}
yapi:http://yapi.demo.qunar.com/
例子:手写注册服务
步骤:
- 启动单节点eureka,7900。
- 打开yapi。yapi->Spring Cloud学习->测试集合->Eureka->向EurekaServer注册服务。
- 执行访问,查看eureka server控制台。
ps:一些语言也有Eureka Client的开源实现,比如node.JS
1.7 Eureka 原理
-
本质:存储了每个客户端的注册信息。EurekaClient从EurekaServer同步获取服务注册列表。通过一定的规则选择一个服务进行调用。
-
Eureka架构图
《 Eureka架构图》
-
详解
- 服务提供者:是一个eureka client,向Eureka Server注册和更新自己的信息,同时能从Eureka Server注册表中获取到其他服务的信息。
- 服务注册中心:提供服务注册和发现的功能。每个Eureka Cient向Eureka Server注册自己的信息,也可以通过Eureka Server获取到其他服务的信息达到发现和调用其他服务的目的。
- 服务消费者:是一个eureka client,通过Eureka Server获取注册到其上其他服务的信息,从而根据信息找到所需的服务发起远程调用。
- 同步复制:Eureka Server之间注册表信息的同步复制,使Eureka Server集群中不同注册表中服务实例信息保持一致。
- 远程调用:服务客户端之间的远程调用。
- 注册:Client端向Server端注册自身的元数据以供服务发现。
- 续约:通过发送心跳到Server以维持和更新注册表中服务实例元数据的有效性。当在一定时长内,Server没有收到Client的心跳信息,将默认服务下线,会把服务实例的信息从注册表中删除。
- 下线:Client在关闭时主动向Server注销服务实例元数据,这时Client的服务实例数据将从Server的注册表中删除。
- 获取注册表:Client向Server请求注册表信息,用于服务发现,从而发起服务间远程调用。
让我们自己做:如何做。?
客户端:
拉取注册表
从注册表选一个
调用
服务端:
写个web server。
功能:
1、定义注册表:
Map<name,Map<id,InstanceInfo>>。
2、别人可以向我注册自己的信息。
3、别人可以从我这里拉取他人的注册信息。
4、我和我的同类可以共享注册表。
eureka是用:jersey实现,也是个mvc框架。
我们可以自己写个spring boot web实现。
1.7 Eureka Client源码
-
功能复习
https://github.com/Netflix/eureka/wiki/Eureka-REST-operations 注意地址中的v2 是没有的。 查询所有实例信息:http://localhost:7900/eureka/apps 注册服务:http://localhost:7900/eureka/apps/{applicationName}
《Eureka Client工作流程图》
-
源码解读
下面的讲解按照顺序进行。
-
spring boot项目引入eureka-client依赖,并注入spring 容器。
在spring-boot项目中pom文件里面添加的依赖中的bean。是如何注册到spring-boot项目的spring容器中的呢?spring.factories文件是帮助spring-boot项目包以外的bean(即在pom文件中添加依赖中的bean)注册到spring-boot项目的spring容器的。
由于@ComponentScan注解只能扫描spring-boot项目包内的bean并注册到spring容器中,因此需要@EnableAutoConfiguration(在SpringBootApplication下),注解来注册项目包外的bean。而spring.factories文件,则是用来记录项目包外需要注册的bean类名。
点进去@SpringBootApplication注解,发现@EnableAutoConfiguration。点@EnableAutoConfiguration进去。
@Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {
点AutoConfigurationImportSelector进去
发现下面代码 @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }
此方法时,向spring ioc容器注入bean。selectImports,返回bean全名。import将bean全名注入。而注入的bean都是些什么呢?
点:getAutoConfigurationEntry进去,有一句
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
点getCandidateConfigurations进去:
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
点SpringFactoriesLoader进去:
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
-
找eureka client 配置相关类
在api-listen-order(其他eureka client项目均可)项目中,找到 spring-cloud-netflix-eureka-client-2.1.2.RELEASE下META-INF下spring.factories。此文件中,有如下配置信息: EurekaClientAutoConfiguration(Eureka client自动配置类,负责Eureka client中关键beans的配置和初始化), RibbonEurekaAutoConfiguration(Ribbon负载均衡相关配置) EurekaDiscoveryClientConfiguration(配置自动注册和应用的健康检查器)。
-
EurekaDiscoveryClientConfiguration介绍
找到此类:org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration中的注解@ConditionalOnClass(EurekaClientConfig.class),
-
EurekaClientConfig介绍
点击进去查看EurekaClientConfig是个接口,查看其实现类EurekaClientConfigBean。此类里封装了Eureka Client和Eureka Server交互所需要的配置信息。看此类代码: public static final String PREFIX = "eureka.client"; 表示在配置文件中用eureka.client.属性名配置。
-
Eureka 实例相关配置
从org.springframework.cloud.client.discovery.DiscoveryClient顶级接口入手,前面介绍过spring common。看其在Eureka中的实现类org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient。有一个属性: private final EurekaClient eurekaClient,查看其实现类:com.netflix.discovery.DiscoveryClient。 有一个属性: private final ApplicationInfoManager applicationInfoManager(应用信息管理器,点进去此类,发现此类总有两个属性: private InstanceInfo instanceInfo; private EurekaInstanceConfig config; 服务实例的信息类InstanceInfo和服务实例配置信息类EurekaInstanceConfig)。
-
InstanceInfo介绍
打开InstanceInfo里面有instanceId等服务实例信息。 InstanceInfo封装了将被发送到Eureka Server进行注册的服务实例元数据。它在Eureka Server列表中代表一个服务实例,其他服务可以通过instanceInfo了解到该服务的实例相关信息,包括地址等,从而发起请求。
-
EurekaInstanceConfig介绍
EurekaInstanceConfig是个接口,找到它的实现类org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean。 此类封装了EurekaClient自身服务实例的配置信息,主要用于构建InstanceInfo。看到此类有一段
-