文章目录
一. Eureka是什么?
Eureka是Springcolud生态中的一员,充当注册中心的责任。当然这只是注册中心实现的方案之一,相关的技术组件还有Zookeeper
,Consul
,Nacos
,现在使用Eureka的公司应该很少了,但是一些老项目可能还在用,所以小编觉得还是有学习的必要,本篇博客类似一个学习笔记,实际技术参考价值不大。
假如我们的服务提供者user-service部署了多个实例,如图:
大家思考几个问题:
- order-service在发起远程调用的时候,该如何得知user-service实例的ip地址和端口?
- 有多个user-service实例地址,order-service调用时该如何选择?
- order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
这些问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka,其结构如下:
回答之前的各个问题。
问题1
:order-service如何得知user-service实例地址?
获取地址信息的流程如下:
- user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端)这个叫
服务注册
。 - eureka-server保存服务名称到服务实例地址列表的映射关系
- order-service根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取
问题2
:order-service如何从多个user-service实例中选择具体的实例?
- order-service从实例列表中利用负载均衡算法选中一个实例地址
- 向该实例地址发起远程调用
问题3
:order-service如何得知某个user-service实例是否依然健康,是不是已经宕机?
- user-service会每隔一段时间(默认30秒)向eureka-server发起请求,报告自己状态,称为心跳检测
- 当超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除
- order-service拉取服务时,就能将故障实例排除了
1. 什么是服务治理?
在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
2. 什么是服务注册?
Eureka采用了CS的设计架构,Eureka Server作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何rpc远程框架中,都会有个注册中心(存放服务地址相关信息(接口地址))
3. 两组件
Eureka包含两个组件:Eureka Server
和Eureka Client
Eureka Server提供服务注册服务:
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServerr中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
EurekaClienti通过注册中心进行访问:
是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器,在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒少)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳Furekaserver将会从服务注册耒中把文个服务节点移除(默认90秒)
二. 单机版Eureka构建
1. EurekaServer代码模块构建
注意
:注册中心服务端eureka-server,这必须是一个独立的微服务
在父工程下新建一个工程模块,将以下依赖信息添加到子工程的POM文件中
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
编写application.yml 配置文件内容如下:
server:
port: 7001 #占用端口
spring:
application:
name: eureka-server #服务名
eureka:
instance:
hostname: localhost #eureka服务端的实例名字
client:
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
子模块主启动类内容,一定要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能。
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
配置完直接启动子模块,访问 localhost:10086,看到下面的界面就是成功了。
2. 服务注册
在需要注册为服务的模块的PMO文件中添加以下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
然后在需要在注册为服务的模块的主启动类上使用@EnableEurekaServer注解
修改注册为服务的模块的application.yml
spring:
application:
name: userservice
eureka:
client:
register-with-eureka: true #表示是否要将自己注册进EurekaServer 默认为true
fetchRegistry: true #是否从EurekaServer抓取己有的注册信息,默认true。单节点无所谓,集群必须设置true才能配合ribbon使用负载均衡
service-url:
defaultZone: http://127.0.0.1:10086/eureka #EurekaServer地址
启动这个被注册为服务的模块,再访问localhost:10086 就可以看到被注册的服务了
可以看到模块的服务名就是注册到EurekaServer的名称
三. 集群版Eureka构建
1. EurekaServer搭建
在上个模块的基础上再搭建一个模块,作为EurekaServer,将以下依赖信息添加到新建工程的POM文件中:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
找到C:Vindows\System32\drivers\etc路径下的hosts文件,将两个映射内容添加进去
- 127.0.0.1 eureka7001.com
- 127.0.0.1 eureka7002.com
编写application.yml 配置文件内容如下:
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名字
client:
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/ #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
修改上一个7001的application.yml 配置文件内容如下:
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名字
client:
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/ #设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
主启动类和上一个模块一样即可,不要忘记添加一个@EnableEurekaServer注解,集群版的EurekaServer搭建其实就是一个相互注册的过程。
紧接着直接启动两个模块即可。
2. 服务注册
将服务添加到Eureka集群中和将服务添加到单击版的Eureka中有所不同,不同点主要体现在配置文件上
首先将以下依赖信息添加到想要添加到注册中心的模块的POM文件中:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
修改application.yml 具体修改内容如下:
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
最后启动模块,查看EurekaWEB控制界面是否注册成功即可
注意: 在启动注册模块前,集群的EurekaServer模块都需要启动起来。
在两个EurekaWEB控制界面都可以看到注册的信息。
通过配置文件中服务名的一致,可以注册多个相同业务功能的服务,这样在别的服务调用该种业务服务时就可以配置负载均衡:
spring:
application:
name: cloud-payment-service #通过服务名的一致配置多个相同的实例
四. 微服务信息完善
1. 后台管理界面完善
上面服务搭建的面临的问题:
- 注册的服务在后台管理界面以主机名的方式显示
- 访问信息无IP地址显示不方便后期维护
首先要保证在注册的服务模块中有以下两个依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后对application.yml配置文件进行修改:
eureka:
client:
register-with-eureka: true #是否向注册中心注册自己
fetchRegistry: true #是否从注册中心抓取已有的注册信息 默认true,集群必须设置为true
service-url:
# 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://localhost:7001/eureka #单机版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001 # 主机名设置
prefer-ip-address: true #访问路径可以显示IP地址
访问路径可以显示IP地址,鼠标移动到主机名上时可以看到IP和端口信息
2. 服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息。
修改注册为服务的模块代码:
@Resource
private DiscoveryClient discoveryClient;
@GetMapping(value = "/payment/discovery")
public Object discovery(){
// 服务列表
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("***** element:"+element);
}
// 根据服务名称获取微服务的相关信息
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
for (ServiceInstance instance : instances) {
// Sercicsis 主机名 端口 uri地址
log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
}
// 注册的微服务清单信息
return this.discoveryClient;
}
最后不要忘了在主启动类上添加一个@EnableDiscoveryClient注解,这样才有效。
五. Eureka自我保护
保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:
EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT.
RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE。
一句话:某时刻某一个微服务不可用了,Eureka.不会立刻清理,依旧会对该微服务的信息进行保存。
1. 自我保护机制
自我保护机制:默认情况下EurekaClient定时向EurekaServer端发送心跳包如果Eureka在servery端在一定时间内(默认9O秒)设有收到EurekaClient发送心跳包,便会直接从服务注册列表中剔除该服务,但是在短时间(90秒中)内丢失了大量的服务实例心跳,这时候EurekaServers会开启自我保护机制,不会剔除该服务(该现象可能出现在如果网络不通但是EurekaClient为出现宕机,此时如果换故别的注册中心如果一定时间内没有收到心跳会将剔除该服务,这样就出现了严重失误,因为客户端还能正常发送心跳,只是网络延迟问题,而保护模式是为了解决此问题而产生的)
默认情况下,如果EurekaServeri在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险了一因为微务本身其实是健康的,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题一当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
主要是为了EurekaClient正常运行,但是与EurekaServerl网络不通情况下,EurekaServer不会立刻将EurekaClient服务剔除。
在自我保护模式中,Eureka Server会保护服务注册表中的信息,不再注销任何服务实例
。
2. 怎么禁止自我保护
禁止自我保护这样一旦服务发生故障下线,注册中心将会立马剔除服务,默认自我保护是开启的,想要关闭整合功能只需要修改EurekaServerl的模块代码:
#集群版
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名字
client:
register-with-eureka: false #表示不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7001.com:7001/eureka/
# defaultZone: http://eureka7002.com:7002/eureka/ 这个是集群版开启 互相注册
server:
## 关闭自我保护机制,保证不可用服务被及时踢除
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000 # 心跳检测间隔时间 单位是毫秒
在web控制台,看到如下内容证明自我保护已经关闭。
服务模块也可以对保护机制进行一些相关的配置:
eureka:
client:
register-with-eureka: true #是否向注册中心注册自己
fetchRegistry: true #是否从注册中心抓取已有的注册信息 默认true,集群必须设置为true
service-url:
# 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
# defaultZone: http://localhost:7001/eureka #单机版
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001
prefer-ip-address: true #访问路径可以显示IP地址
# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
# lease-renewal-interval-in-seconds: 1
# Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
# lease-expiration-duration-in-seconds: 2