1 Spring Cloud Eureka 简介
Netflix 在线影片公司开源的一个服务注册与发现的组件。
2 Spring Cloud Eureka 和 Zookeeper 的区别
2.1 什么是 CAP 原则(面试)
在分布式微服务里面 CAP 定理
问:为什么 zookeeper 不适合做注册中心?
CAP 原则又称 CAP 定理,指的是在一个分布式系统中,
一致性(Consistency)
可用性(Availability)
分区容错性(Partition tolerance)(这个特性是不可避免的)
CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。
2.2 分布式特征
C : 数据的一致性 (A,B,C 里面的数据是一致的)
Zk 注重数据的一致性。
Eureka 不是很注重数据的一致性!
A: 服务的可用性(若 zk 集群里面的 master 挂了怎么办)Paxos(多数派)
在 zk 里面,若主机挂了,则 zk 集群整体不对外提供服务了,需要选一个新的出来(120s
左右)才能继续对外提供服务!
Eureka 注重服务的可用性,当 Eureka 集群只有一台活着,它就能对外提供服务
P:分区的容错性(在集群里面的机器,因为网络原因,机房的原因,可能导致数据不会里面
同步),它在分布式必须需要实现的特性!
Zookeeper 注重数据的一致性,CP zk(注册中心,配置文件中心,协调中心)
Eureka 注重服务的可用性 AP eureka (注册中心)
3 Spring Cloud 其他注册中心
Spring Cloud 还有别的注册中心 Consul ,阿里巴巴提供 Nacos 都能作为注册中心,我们
的选择还是很多。
Consul: https://spring.io/projects/spring-cloud-consulConsul
Nacos: https://nacos.io/zh-cn/
4 Spring Cloud Eureka 快速入门

4.1 搭建 Eureka-server
-
Spring Initializr 创建 Module
-
选择依赖:Eureka Server
-
修改配置文件 application.yml
server: port: 8761 # eureka 默认端口 8761, redis 6379, tomcat 8080 spring: application: name: eureka-server # 应用名称 -
启动类添加 @EnableEurekaServer 注解
-
启动应用,观察控制台输出

-
访问 http://localhost:8761

在 eureka 里面是通过 spring.application.name 来区分服务的
4.2 搭建 Eureka-client
-
Spring Initializr 创建 Module
-
选择依赖:Spring Web & Eureka Client
-
修改配置文件 application.yml
server: port: 8080 # 客户端的端口没有要求 spring: application: name: eureka-client-a # 注册就是将自己的信息发送到注册中心 eureka: client: service-url: defaultZone: http://localhost:8761/eureka -
启动类添加 @EnableEurekaClient 注解
-
启动应用,观察控制台输出

4.3 搭建同一应用两台实例


添加配置项:--server.port=8083 然后就有信的启动项了。

4.4 注册中心的状态认识
UP: 服务是上线的,括号里面是具体服务实例的个数,提供服务的最小单元
DOWN: 服务是下线的
UN_KONW: 服务的状态未知

5 常用配置文件设置
5.1 常见的应用需求
- 注册中心,有一个容器/列表,保存服务的信息。
- 注册中心有一个定期删除机制,应用下线了 or 挂了
- 主动下线怎么处理、被动下线怎么处理
- 应用和注册中心建立联系 —— 心跳机制
- 客户端可以将服务列表缓存一份到本地 —— 脏读问题
- 缓存列表可以设置拉取时间
- 一段时间内,大量应用均不与本机建立联系,该怎么办?
eureka-server 不会剔除任何一个服务
5.2 server 中常用的配置
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
server:
eviction-interval-timer-in-ms: 30000 # 清除无效节点的频率(毫秒)--定期删除
enable-self-preservation: true # server 的自我保护机制,避免因为网络原因造成误剔除,生产环境建议打开
renewal-percent-threshold: 0.85 # 85%,如果在一个机房的 client 端,15 分钟内有 85%的 client 没有续约,那么则可能是
# 网络原因,认为服务实例没有问题,不会剔除他们,宁可放过一万,不可错杀一个,确保高可用
client:
service-url: # eureka 服务端和客户端的交互地址,集群用,隔开
defaultZone: http://localhost:8761/eureka
fetch-registry: true # 是否拉取服务列表
register-with-eureka: true # 是否注册自己(单机 eureka 一般关闭注册自己,集群注意打开)
instance:
hostname: localhost # 服务主机名称
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 实例 id
prefer-ip-address: true # 服务列表以 ip 的形式展示
lease-renewal-interval-in-seconds: 10 # 表示 eureka client 发送心跳给 server 端的频率
lease-expiration-duration-in-seconds: 20 #表示 eureka server 至上一次收到 client 的心跳之后,等待下一次心跳的超时时
# 间,在这个时间内若没收到下一次心跳,则将移除该实例5.3 client 中常用的配置
server:
port: 8080
spring:
application:
name: eureka-client
eureka:
client:
service-url: #eureka 服务端和客户端的交互地址,集群用,隔开
defaultZone: http://localhost:8761/eureka
register-with-eureka: true #注册自己
fetch-registry: true #拉取服务列表
registry-fetch-interval-seconds: 5 # 表示 eureka-client 间隔多久去拉取服务注册信息
instance:
hostname: localhost # 服务主机名称
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port} # 实例 id
prefer-ip-address: true # 服务列表以 ip 的形式展示
lease-renewal-interval-in-seconds: 10 # 表示 eureka client 发送心跳给 server 端的频率
lease-expiration-duration-in-seconds: 20 #表示 eureka server 至上一次收到 client 的心跳之后,等待
# 下一次心跳的超时时间,在这个时间内若没收到下一次心跳,则将移除该实例6 构建高可用的 Eureka-Server 集群

6.1 错误注册方式
创建三个应用,对应的配置文件如下(仅修改了端口)
server:
port: 8761
spring:
application:
name: eureka-server #服务名称
eureka:
client:
fetch-registry: true #是否拉取服务列表
register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务)
service-url:
defaultZone: http://localhost:8762/eureka/,http://localhost:8763/eureka/
server:
eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
instance:
lease-expiration-duration-in-seconds: 90server:
port: 8762
spring:
application:
name: eureka-server #服务名称
eureka:
client:
fetch-registry: true #是否拉取服务列表
register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务)
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8763/eureka/
server:
eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
instance:
lease-expiration-duration-in-seconds: 90server3 略。
启动后,查看 http://localhost:8761 集群中只有一个机器,出错。
6.2 解决出错的注册方式
解决方法:在本地 hosts 文件中创建域名与 IP 的映射关系
- 修改 hosts 文件:
C:\Windows\System32\drivers\etc - 添加下面内容:
127.0.0.1 peer1
127.0.0.1 peer2
127.0.0.1 peer3
- 控制台更新映射
ipconfig /flushdns - 更新上面的配置文件,将所有的
localhost更换为对应的域名地址,如下所示:
server:
port: 8761
spring:
application:
name: eureka-server #服务名称
eureka:
client:
fetch-registry: true #是否拉取服务列表
register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务)
service-url:
defaultZone: http://peer2:8762/eureka/,http://peer3:8763/eureka/
server:
eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
instance:
lease-expiration-duration-in-seconds: 90- 最佳优化版本:
此时,可以通过复制启动项,并且仅仅修改端口号(如 4.3 节所示),就可以完成了
server:
port: 8761
spring:
application:
name: eureka-server #服务名称
eureka:
client:
fetch-registry: true #是否拉取服务列表
register-with-eureka: true #是否注册自己(集群需要注册自己和拉取服务)
service-url:
defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/
server:
eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
instance:
lease-expiration-duration-in-seconds: 90
6.3 集群的使用
修改客户端的配置文件
server:
port: 8001
spring:
application:
name: eureka-client-a
eureka:
client:
# eureka服务端和客户端的交互地址,集群使用,来分制
service-ur1:
defaultZone: http://peer1:8761/eureka/,http://peer2:8761/eureka/,http://peer3:8761/eureka
register-with-eureka: true #注册自己到eureka-server 上#拉去服务列表
fetch-registry: true
instance:
instance-id: $springapplication,name);$(server,port) #注到eureka-server的实例名称一般这样显示
lease-renewal-interval-in-seconds: 3 #eureka客户向服务发送心跳时间,每网30s 发送一次7 其他
了解一下一个分布式数据一致性协议 Paxos raft
http://thesecretlivesofdata.com/raft/
zk 是 Paxos
eureka 没有分布式数据一致性的机制节点都是相同的
nacos raft
在有主从模式的集群中一般都要遵循这样的协议才可以稳定对外提供服务
Zookeeper Paxos
Nacos raft
8 Eureka 概念的理解
8.1 服务的注册
当项目启动时(eureka 的客户端),就会向 eureka-server 发送自己的元数据(原始数据)
(运行的 ip,端口 port,健康的状态监控等,因为使用的是 http/ResuFul 请求风格),
eureka-server 会在自己内部保留这些元数据(内存中)。(有一个服务列表)(restful 风
格,以 http 动词的请求方式,完成对 url 资源的操作)
8.2 服务的续约
项目启动成功了,除了向 eureka-server 注册自己成功,还会定时的向 eureka-server 汇
报自己,心跳,表示自己还活着。(修改一个时间)
8.3 服务的下线(主动下线)
当项目关闭时,会给 eureka-server 报告,说明自己要下机了。
8.4 服务的剔除 (被动下线,主动剔除)
当项目超过了指定时间没有向 eureka-server 汇报自己,那么 eureka-server 就会认为此
节点死掉了,会把它剔除掉,也不会放流量和请求到此节点了。
9 Eureka 源码分析
9.1 Eureka 运作原理的特点
Eureka-server 对外提供的是 restful 风格的服务
以 http 动词的形式对 url 资源进行操作 get post put delete
http 服务 + 特定的请求方式 + 特定的 url 地址
只要利用这些 restful 我们就能对项目实现注册和发现
只不过,eureka 已经帮我们使用 java 语言写了 client,让我们的项目只要依赖 client 就
能实现注册和发现!
Server 端使用 ConcurrentHashMap 来进行存储数据:
- Key 为应用名称
- Value 为 Map 对象,其中,key 为 instanceID,value 为 InstanceInfo。
instanceID —— 前面展示了,默认是“主机号:应用名称:端口号”
instanceInfo —— 后面有代码图
9.2 服务注册的源码分析
register 方法


9.3 服务续约的源码分析
renew 方法 —— put
9.4 服务剔除的源码分析(被动下线)
- server 端采取随机删除
- evit 方法
- 定时任务
9.5 服务下线的源码分析
- unregister 方法 - delete 方法
9.6 服务发现(源头)
根据服务名称发现服务的实例过程
客户端会在本地缓存服务端的列表
拉取列表是有间隔周期的 (导致服务上线客户端不能第一时间感知到 (可以容忍))
其实每次做服务发现,都是从本地的列表来进行的
