注册中心
在微服务中,许多业务被拆分成不同的服务,那么服务与服务之间无法避免相互调用。那么原来在同一个进程中的业务逻辑,现在可能分布到了不同的地址。
Spring Cloud 解决服务间的调用采用的是基于REST的HTTP调用,如果在A中写上B服务的地址,那么B改动的时候,A也要对应的修改URL,这样的做法耦合性太强了。此时就需要注册中心对这种场景进行解耦。
注册中心的构成
注册中心中有三个角色的划分:注册中心、服务提供者、服务消费者。
其中,服务提供者向注册中心注册服务,注册中心将该服务注册的接口进行暴露,当服务消费者需要服务调用的时候,从注册中心拿到服务注册表,然后找到相应服务的信息对该服务进行调用。
Eureka注册
image.png当客户端注册Eureka时,它提供有关自身的元数据,例如主机和端口,运行状况指示符URL,主页等。Eureka从属于服务的每个实例接收心跳消息。如果心跳失败超过可配置的时间表,则通常将该实例从注册表中删除。
Eureka获取注册表信息
# 是否允许获取注册表信息
eureka.client.fetch-registry=true
# client定期更新本地缓存的时间
eureka.client.registry-fetch-interval-seconds=30
Eureka续约
image.png通过心跳检测
Eureka Server宕机了,服务之间还可以相互调用么
也许可以,在服务提供者的服务地址不变的时候,如果服务消费者此时缓存了注册表,是可以进行服务调用的。
Eureka 配置
package com.xjm.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**
* @EnableEurekaServer 开启EurekaServer的功能
*/
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
配置文件
# 服务名
spring.application.name=eureka
# 端口号
server.port=1111
# eureka启动时,默认会把自己也当成一个服务,设置成false就会被忽略自己.
# 单点注册中心不需要注册自己,但是在集群环境中,需要开启,让eureka服务互相感知对方的存在
eureka.client.register-with-eureka=false
# 表示是否从 eureka上获取注册信息
eureka.client.fetch-registry=false
注册中心UI的说明
Eureka为开发者提供了一个UI界面进行服务健康监控.
开启健康检查
eureka.client.healthcheck.enabled=true
Eureka集群的搭建
- 为什么需要集群呢?
这就涉及到分布式系统中著名的CAP原理了.
在分布式系统中,要么选择CP,要么选择AP。而Eureka是AP的一种实现,它是保证高可用的,所以我们的服务要具备容灾机制,搭建集群即使当前注册中心宕机了,也可以迅速转换到另一个注册中心进行服务注册与消费,当然,CP的注册中心也是可以搭建集群的,不过两者的故障处理是有区别的。
- 修改hosts文件
找到你的hosts文件,添加上这句
## 当访问eurekaA、eurekaB的时候,
## DNS会解析到120.0.0.1这个ip地址
127.0.0.1 eurekaA eurekaB
- 相互注册
eurekaA配置文件
# 服务名
spring.application.name=eureka
# 端口号
server.port=1111
# host名字
eureka.instance.hostname=eurekaA
# eureka启动时,默认会把自己也当成一个服务,设置成false就会被忽略自己.
# 单点注册中心不需要注册自己,但是在集群环境中,需要开启,让eureka服务互相感知对方的存在
eureka.client.register-with-eureka=true
# 表示是否从 eureka上获取注册信息
eureka.client.fetch-registry=true
# 将A注册到B中,如果需要增加身份验证,那么可以使用以下形式:
# http://user:password@localhost:port/eureka
eureka.client.service-url.defaultZone=http://eurekaB:1112/eureka
eurekaB配置文件
# 服务名
spring.application.name=eureka
# 端口号
server.port=1112
# host名字
eureka.instance.hostname=eurekaB
# eureka启动时,默认会把自己也当成一个服务,设置成false就会被忽略自己.
# 单点注册中心不需要注册自己,但是在集群环境中,需要开启,让eureka服务互相感知对方的存在
eureka.client.register-with-eureka=true
# 表示是否从 eureka上获取注册信息
eureka.client.fetch-registry=true
# 将B注册到A中
eureka.client.service-url.defaultZone=http://eurekaA:1111/eureka
其中“defaultZone”是一个魔术字符串后备值,为任何不表示首选项的客户端提供服务URL(即它是有用的默认值),spring官方文档中特地指明改变量必须声明为驼峰。
打包部署
使用Maven对项目进行打包,注意打成jar包
image.png可以看到,在target目录下已经产生了jar包
image.png最后,我们通过spring.profiles.active
来指定当前程序使用什么配置文件
java -jar eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=a
java -jar eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=b
可以看到,集群环境已经成功搭建起来了
image.png
Eureka的高可用性
Eureka是没有持久化这个概念的,它通过让注册表中的实例发送心跳(默认为30S)来保持当前的注册表是最新的,存储的区域为内存。
不仅如此,每个客户端都会存储Eureka注册的内存缓存,因此,他们不必为注册表提供每个服务请求.
集群环境下,如果某个Eureka Server发生故障,那么Ribbon会自动负载均衡到其他的Eureka Server,等待此Eureka Server恢复后,再进行信息同步。这就会出现数据的不一致,但是最终趋于一致
Eureka自我保护
如果大量的服务都续约失败->90S内丢失了超过阈值的服务实例心跳,那么Eureka会进入自我保护模式,它会将这些失效的实例保护起来,而不是去剔除掉它们。
如果3次(90S)内只有少量服务没有发送心跳,那么Eureka会把这些服务从注册表中剔除掉。
TIPS:一般建议在本地测试,开发环境关闭自我保护机制,真实,生产环境开启自我保护机制
server:
#测试时关闭自我保护机制,保证不可用服务及时剔除
enable-self-preservation: false
#间隔10秒剔除
eviction-interval-timer-in-ms: 10000
网友评论