文章目录
- Eureka基础概念
-
- Eureka概述
- Eureka架构图
- Eureka集群架构图
- Eureka关键概念
- Eureka的自我保护模式
- 创建Eureka服务端
- 服务提供者cloud-provider-8001入驻进EurekaServer
- 消费者模块入驻进EurekaServer
- Eureka工作原理
- Eureka集群环境构建
- 将服务注册进Eureka集群
- 服务提供端搭建集群
- actuator微服务信息完善
- 服务发现Discovery
- 禁用自我保护模式
Eureka基础概念
Eureka概述
Eureka:服务注册与发现提供了一个服务注册中心、服务发现的客户端,还有一个方便查看所有注册的服务的界面。所有的服务使用Eureka的服务发现客户端来将自己注册到Eureka的服务器上。
Eureka架构图
Spring Cloud封装了Netflix 公司开发的Eureka模块来实现服务治理。
在传统的RPC远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册。
Eureka采用了CS的设计架构,Eureka Sever作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行。
在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者\服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地RPC调用。RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何RPC远程框架中,都会有一个注册中心存放服务地址相关信息(接口地址)。
Eureka由两个组件组成: Eureka服务器和Eureka客户端。
Eureka Server提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
EurekaClient通过注册中心进行访问
它是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)。
Eureka集群架构图
Eureka关键概念
- 服务注册:register
- 服务续约:renew, 客户端默认每隔30秒向服务器发送一次心跳进行续约,如果服务器90秒内没有收到心跳,则将该客户端剔除
- 获取服务注册列表信息:fetch registries
- 服务下线:cancel
- 服务剔除eviction
Eureka的自我保护模式
- 默认情况下,如果Eureka Server在一定时间内没有接收到某个微服务实例的心跳,Eureka Server将 会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通 信,这就可能变得非常危险了----因为微服务本身是健康的,此时本不应该注销这个微服务。
- Eureka Server通过“自我保护模式”来解决这个问题- - -当Eureka Server节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式, Eureka Server就会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server节点会自动退出自我保护模式。
- 自我保护模式是一种对网络异常的安全保护措施。使用自我保护模式,可以让Eureka集群更加健壮、 稳定。
- 在Spring Cloud中,可以使用eureka.server.enable-self-preservation=false来禁用自我保护模式(不建议禁用)
- 简言之:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存。
创建Eureka服务端
1.新建Module
创建名为cloud-eureka-server7001的Maven工程。
2.修改pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>cloud-kernel</artifactId>
<groupId>com.kernel.springcloud</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka-server7001</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<!-- 我们自己的公共模块 -->
<dependency>
<groupId>com.kernel.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>${project.version}</version>
</dependency>
<!--服务中心 -->
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
3.编写application.yml配置文件
server:
port: 7001
eureka:
instance:
hostname: localhost # eureka服务端的实例名称
client:
# false表示不向注册中心注册自己。
register-with-eureka: false
# false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与Eureka server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
4.编写启动类
@EnableEurekaServer注解 表示 Eureka服务端
@SpringBootApplication
@EnableEurekaServer
public class EurekaMainApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaMainApplication.class,args);
}
}
5.测试
测试运行EurekaMainApplication,浏览器输入http://localhost:7001/回车,会查看到Spring Eureka服务主页。
服务提供者cloud-provider-8001入驻进EurekaServer
EurekaClient端cloud-provider-8001将注册进EurekaServer成为服务提供者provider。
1.修改cloud-provider-8001的pom文件
添加spring-cloud-starter-netflix-eureka-client依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.修改application.yml配置文件
server:
port: 8001
spring:
application:
name: cloud-provider-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.jdbc.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/idata_baiir?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username: ******
password: ******
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.kernel.entity # 所有Entity别名类所在包
eureka:
client:
# 表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
3.修改主启动类
@SpringBootApplication
@EnableEurekaClient //<-----添加该注解
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
4.测试
启动cloud-provider-8001和cloud-eureka-server7001工程。
浏览器输入 http://localhost:7001/ 主页内的Instances currently registered with Eureka会显示cloud-provider-8001的配置文件application.yml设置的应用名cloud-provider-service
消费者模块入驻进EurekaServer
EurekaClient端cloud-consumer-80将注册进EurekaServer成为服务消费者consumer。
1.修改cloud-consumer-80的pom文件
添加spring-cloud-starter-netflix-eureka-client依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2.修改application.yml配置文件
server:
port: 80
spring:
application:
name: cloud-consumer-service
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
3.修改主启动类
@SpringBootApplication
@EnableEurekaClient//<--- 添加该注解
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class,args);
}
}
4.测试
启动cloud-provider-8001、cloud-eureka-server7001和cloud-consumer-80这三工程。
浏览器输入 http://localhost:7001 , 在主页的Instances currently registered with Eureka将会看到cloud-provider-8001、cloud-consumer-80两个工程名。
Eureka工作原理
Eureka集群环境构建
Eureka server搭建集群不同与传统集群,每个server是互等的1在向23注册时1就相当于客户端,需要向23注册信息的同时还要获取信息。所以 defaultZone注册时如1需注册23的server地址(不能注册自己的地址)注册完123会在系统趋于平稳进行复制 达到信息共享统一
创建cloud-eureka-server7002工程 步骤同上
hosts文件,修改映射配置添加进hosts文件
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
修改cloud-eureka-server7001配置文件
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
defaultZone: http://eureka7002.com:7002/eureka/
#单机就是7001自己
#defaultZone: http://eureka7001.com:7001/eureka/
修改cloud-eureka-server7002配置文件
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
defaultZone: http://eureka7001.com:7001/eureka/
#单机就是7002自己
#defaultZone: http://eureka7002.com:7002/eureka/
将服务注册进Eureka集群
将它们的配置文件的eureka.client.service-url.defaultZone进行修改
eureka:
client:
#表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka
服务提供端搭建集群
前边已经将eureka注册中心搭建成集群,现在把我们的服务端也搭建为集群环境。
参考cloud-provider-8001 新建 cloud-provider-8002
1.新建cloud-provider-8002 模块
2.修改POM
3.写YML - 端口改为8002 (除了端口号其余全一样)
server:
port: 8002
spring:
application:
name: cloud-provider-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.jdbc.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/idata_baiir?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT
username: ******
password: ******
mybatis:
mapperLocations: classpath:mapper/*.xml
type-aliases-package: com.kernel.entity # 所有Entity别名类所在包
eureka:
client:
# 表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
4.编写主启动类
5.编写业务代码
为了测试,我们在代码里加入调用的端口号
可以看到 cloud-provider-service 下有俩个服务
负载均衡
cloud-consumer-80服务访问地址不能写死
使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
@Configuration
public class ApplicationContextConfig {
@Bean
@LoadBalanced //使用@LoadBalanced注解赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
测试
结果:负载均衡效果达到,8001/8002端口交替出现
actuator微服务信息完善
instance-id:主机名称:服务名称修改(也就是将IP地址,换成可读性高的名字)
prefer-ip-address:访问信息有IP信息提示
eureka:
client:
# 表示是否将自己注册进Eurekaserver默认为true。
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka
instance:
instance-id: ${spring.application.name}:${server.port}
prefer-ip-address: true #访问路径可以显示IP地址
服务发现Discovery
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
修改cloud-provider-8001的Controller
@Api(tags = "用户管理接口")
@RestController
@Slf4j
@RequestMapping("/user")
public class UserController {
@Autowired
private IUserTestService userTestService;
@Autowired
private DiscoveryClient discoveryClient;
@Value("${server.port}")
private Integer serverPort;
@ApiOperation(value = "服务发现Discovery")
@GetMapping(value = "/get/discovery")
public Object discovery() {
List<String> services = discoveryClient.getServices();
for (String element : services) {
log.info("*****element: " + element);
}
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PROVIDER-SERVICE");
for (ServiceInstance instance : instances) {
log.info(instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
}
return this.discoveryClient;
}
}
修改主启动类
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient//添加该注解
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
禁用自我保护模式
在eurekaServer端7001处设置关闭自我保护机制
默认,自我保护机制是开启的
使用eureka.server.enable-self-preservation = false可以禁用自我保护模式
eureka:
...
server:
#关闭自我保护机制,保证不可用服务被及时踢除
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000 # 清理间隔(单位毫秒,默认是60*1000)
生产者客户端eurekaClient端8001
eureka:
...
instance:
instance-id: ${spring.application.name}:${server.port}
prefer-ip-address: true
#心跳检测与续约时间
#开发时没置小些,保证服务关闭后注册中心能即使剔除服务
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2
结果:先关闭8001,马上被删除了