eureka注册中心
一、常见的注册中心
eureka | nacos | consul | zookeeper | |
---|---|---|---|---|
公司 | Netflix | Alibaba | HashiCorp | Apache |
CAP | AP | CP+AP | CP | CP |
健康检查 | Client Beat | TCP/HTTP/MySQL/Client Beat | TCP/HTTP/gRPC/Cmd | keep Alive |
雪崩保护 | 有 | 有 | 无 | 无 |
自动注销实例 | 支持 | 支持 | 不支持 | 支持 |
访问协议 | HTTP | HTTP/DNS | HTTP/DNS | TCP |
监听支持 | 支持 | 支持 | 支持 | 支持 |
多数据中心 | 支持 | 支持 | 支持 | 不支持 |
跨注册中心同步 | 不支持 | 支持 | 支持 | 不支持 |
SpringCloud集成 | 支持 | 支持 | 支持 | 支持 |
二、什么是eureka
2.1、注册中心解决了什么问题
在没有注册中心时候,服务间调用需要知道被调方的地址或者代理地址。当服务更换部署地址,就不得不修改调用当中指定的地址或者修改代理配置。
而有了注册中心之后,继续地址都会通过注册中心同步过来,每个服务在调用别人的时候只需要知道服务名称就好啦 ( ̄_, ̄ )
服务治理可以说是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务实例的自动化注册和服务发现
2.2、eureka
eureka采用纯Java实现,除实现了注册中心基本的服务注册和发现之外,极大的满足注册中心的可用性,即使只有一台服务可用,也可以保证注册中心的可用性
eureka实现了SpringCloud的服务注册与发现,同时提供了负载均衡、故障转移等能力
2.3、注册中心三种角色
两种常用注册中心架构对比 ( ̄ε(# ̄)☆╰╮o( ̄皿 ̄///)
Eureka Server
通过Register、Get、Renew等接口提供服务的注册和发现
Service Provider(Application Service)
服务提供方把自身的服务实例注册到Eureka Server中
Application Client (Service Consumer)
服务调用方通过Eureka Server 获取服务列表,消费服务
三、项目搭建
注:版本用自己最新的即可,如果用我的可能会造成版本冲突问题
我采用的是原始的mvn创建聚合工程,也可以使用springBoot创建工程,那样会简单些 (u‿ฺu✿ฺ)
3.1、eureka-server
3.1.1、单节点
父项目eureka
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
</parent>
<properties>
<spring-cloud.version>2021.0.0</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
子项目eureka-server
<parent>
<groupId>com.yxy</groupId>
<artifactId>eureka</artifactId>
<version>1.0.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
junit-vintage-engine和junit-jupiter-engine之间的区别
参考:https://blog.csdn.net/m761383058/article/details/114932648
application.yml
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false # 是否把自己注册到注册中心 默认为true 因为当前eureka-server就是注册中心
fetch-registry: false # 是否从注册中心获取服务注册信息 默认为true
service-url: # 注册中心对外暴露的注册地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
3.1.2、双节点
区别于单节点,只有application.yml有些变化,只是把服务中心地址指向另一个注册中心 Σ( ° △ °|||)︴
并把访问方式由名称+端口改为IP+端口
原:UP (2) - localhost:eureka-server:8761 , localhost:eureka-server:8762
改:UP (2) - 192.168.222.1:8761 , 192.168.222.1:8762
节点一:application.yml
server:
port: 8761
spring:
application:
name: eureka-server
eureka:
instance:
hostname: eureka01 # 主机名为:eureka01
prefer-ip-address: true # 是否使用IP地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} # 访问IP:端口
client: # 设置服务注册中心地址,指向另一个注册中心
service-url: # 注册中心对外暴露的注册地址
defaultZone: http://localhost:8762/eureka/
节点二:application.yml
server:
port: 8762
spring:
application:
name: eureka-server
eureka:
instance:
hostname: eureka02 # 主机名为:eureka01
prefer-ip-address: true # 是否使用IP地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} # 访问IP:端口
client: # 设置服务注册中心地址,指向另一个注册中心
service-url: # 注册中心对外暴露的注册地址
defaultZone: http://localhost:8761/eureka/
3.2、eureka-provider
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
application.yml
server:
port: 7070
spring:
application:
name: service-provider
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client:
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
3.3、eureka-consumer
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
application.yml
server:
port: 9090
spring:
application:
name: service-consumer
eureka:
client:
register-with-eureka: false # 是否将自己注册到注册中心
registry-fetch-interval-seconds: 10 # eureka client 多久去服务器拉取注册信息,默认为30S
service-url:
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
3.4、项目搭建过程可能遇到的问题
3.2.1、eureka-server子工程build标签爆红 (ノへ ̄、)
方法一:
去掉最外层的pluginManagement标签,再重新加载maven。(dependency标签也同理)
方法二:
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</dependency>
四、eureka架构原理
- 服务注册(Register):把自己的IP+端口注册给eureka
- 服务续约(Renew):每30秒定时发送一次心跳,如果90秒未发送心跳,宕机
- 服务下线(Cannel):Provider关闭时,会发送信息把自己从服务列表删除。防止Consumer调用到不存在的服务
- 拉取注册列表(Get Register):获取其他服务列表
- 同步(Replicate):eureka集群中的数据复制与同步
- 远程调用(Make Remote Call):完成服务的远程调用
五、CAP原则
zookeeper 和 eureka中的CP和 AP参考:https://www.cnblogs.com/wei57960/p/12260228.html
1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标 ✧(≖ ◡ ≖✿)
- 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值,即写操作之后的读操作,必须返回该值。(分为弱一致性、强一致性和最终一致性)
- 可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
- 分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
5.1、取舍
- CA/P:如果不要求P(不允许分区),则C(强一致性)和A(可用性)是可以保证的。但其实分区不是你想不想的问题,而是始终会存在,因此CA的系统更多的是允许分区后各子系统依然保持CA
- CP/A:如果不要求A(可用),相当于每个请求都需要在Server之间强一致,而P(分区)会导致同步时间无限延长,如此CP也是可以保证的。很多传统的数据库分布式事务都属于这种模式
- AP/C:要高可用并允许分区,则需放弃一致性。一旦分区发生,节点之间可能会失去联系,为了高可用,每个节点只能用本地数据提供服务,而这样会导致全局数据的不一致性。现在众多的NoSQL都属于此类
5.2、总结
分布式系统必然面对分区容错性的问题,所以就需要在C(一致性)和A(可用性)之间进行取舍 ┑( ̄Д  ̄)┍
像传统的银行项目,必须保证C(一致性),可在A(可用性)和P(分区容错性)之间进行取舍 (;′⌒`)
六、eureka自我保护
eureka自我保护机制,感觉有点像redis哨兵机制 (○` 3′○)
官方定义:自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行 参考:https://www.cnblogs.com/ericnie/p/9393995.html
6.1、启动自我保护条件
eureka各个节点都是平等的,没有zookeeper中角色的概念, 即使N-1个节点挂掉也不会影响其他节点的正常运行
默认情况下,**如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例。**但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制
自我保护模式(默认是开启的)
客户端节点正常的心跳比例低于85%的,也就是超过15%的客户端节点没有正常心跳才会触发自我保护机制
6.2、为什么要开启自我保护
- 当因为网络原因宕机的话,网络恢复的话,节点会退出“自我保护”,可以接着使用 ||ヽ( ̄▽ ̄)ノミ|Ю
- eureka还有客户端缓存功能(也就是微服务的缓存功能),即使eureka集群中所有节点都宕机,微服务的Provider和Consumer都能正常通信
- 微服务的负载均衡策略会自动剔除死亡的微服务节点
七、优雅停服
配置了优雅停服,将不在需要在配置中关闭自我保护
eureka-provider添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
eureka-provider_application.yml
management:
endpoints:
web:
exposure:
incloud: shutdown # 开启 shutdown 端点访问。 '*'开启所有端点但不包括shutdown
endpoint: # 确定要不要开启 shutdown 实现优雅停服
shutdown:
enabled: true # 确定
结果:bye~~~ o( ̄ヘ ̄o#)
八、eureka安全认证
8.1、设置访问时需要密码
eureka-server添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
eureka-server_application.yml
server:
port: 8762
spring:
application:
name: eureka-server
security:
user:
name: root
password: 123456
eureka:
instance:
hostname: eureka02 # 主机名为:eureka01
prefer-ip-address: true # 是否使用IP地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port}
client: # 设置服务注册中心地址,指向另一个注册中心
service-url: # 注册中心对外暴露的注册地址
defaultZone: http://root:123456@localhost:8761/eureka/
eureka-provider_application.yml
defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/
eureka-consumer_application.yml
defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/
!!!!!这时会服务中心没有互相的信息 (○` 3′○)
8.2、过滤CSRF
eureka会自动配置CSRF防御机制,Spring Security 认为POST等等都是有风险的,如果这些method发送过程中没有带上CSRF token的话,会被直接拦截并返回403 forbidden
eureka-server添加配置类
方案一
让CSRF忽略/eureka/**
的所有请求,防御力高 ( ̄_, ̄ )
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
/**
* 为了访问 eureka 控制台和 /actuator 时能做到安全控制
*/
super.configure(http);
/**
* 忽略 /eureka/** 的所有请求
*/
http.csrf().ignoringAntMatchers("/eureka/**");
}
}
方案二
保持密码验证的同时禁用CSRF防御机制,防御力低 Σ( ° △ °|||)︴
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
/**
* 如果直接 disable 的话会把安全认证也禁用掉
*/
http.csrf().disable()
.authorizeHttpRequests()
.anyRequest()
.authenticated()
.and()
.httpBasic();
}
}
九、扩展
Maven 的41种骨架功能介绍 ★,°:.☆( ̄▽ ̄)/$:.°★ 。
参考:https://www.cnblogs.com/iusmile/archive/2012/11/14/2770118.html
eureka集群搭建
spring:
application:
name: eureka
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defalutZone: http://localhost:7900/eureka/,http://localhost:7901/eureka/,http://localhost:7902/eureka/
server:
enable-self-preservation: false
renewal-percent-threshold: 0.85
eviction-interval-timer-in-ms: 1000
use-read-only-response-cache: false
response-cache-update-interval-ms: 1000
---
spring:
config:
activate:
on-profile: 7900
server:
port: 7900
eureka:
instance:
hostname: eureka-7900
---
spring:
config:
activate:
on-profile: 7901
server:
port: 7901
eureka:
instance:
hostname: eureka-7901
---
spring:
config:
activate:
on-profile: 7902
server:
port: 7902
eureka:
instance:
hostname: eureka-7902