Eureka服务注册与发现

一、微服务的注册中心

注册中心可以说是微服务架构中的“通讯录”,它记录了服务和服务地址的映射关系。在分布式架构中,服务会注册到这里,当服务需要调用其他服务时,就会在这里找到服务的地址,进行调用。
在这里插入图片描述

1.1 注册中心的主要作用

服务注册中心(下称注册中心)是微服务架构非常重要的一个组件,在微服务架构里主要起到了协调者的作用。注册中心一般包含如下几个功能:
1、服务发现:

  • 服务注册/反注册:保存服务提供者和服务调者的信息
  • 服务订阅/取消订阅:服务调用者订阅服务提供者的信息,最好有实时推送的功能
  • 服务路由(可选):具有筛选整合服务提供者的能力

2、服务配置:

  • 配置订阅:服务提供者和服务调用者订阅微服务相关的配置
  • 配置下发:主动将配置推送给服务提供者和服务调用者

3、服务健康检测

  • 检测服务提供者的健康状况

1.2 常见的注册中心

Zookeeper
Zookeeper 是一个分布式服务框架,是 Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。简单来说 Zookeeper = 文件系统 + 监听通知机制。

Eureka
Eureka 是在 Java 语言上,基于 RESTful API 开发的服务注册与发现组件,SpringCloud Netflix 中的重要组件。

Consul
Consul 是由 HashiCorp 基于 Go 语言开发的支持多数据中心分布式高可用的服务发布和注册服务软件,采用 Raft 算法保证服务的一致性,且支持健康检查

Nacos
Nacos 是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。简单来说 Nacos 就是注册中心 + 配置中心的组合,提供简单易用的特性集,帮助我们解决微服务开发必会涉及到的服务注册与发现,服务配置,服务管理等问题。Nacos 还是 SpringCloud Alibaba 组件之一,负责服务注册与发现。

组件名语言CAP一致性算法服务健康检查对外暴露接口
EurekaJavaAP可配支持HTTP
ConsulGoCPRaft支持HTTP/DNS
ZookeeperJavaCPPaxos支持客户端
NacosJavaAPRaft支持HTTP

二、Eureka 的概述

2.1 Eureka 的基础知识

Eureka 是 Netflix 开发的服务发现框架,SpringCloud 将它集成在自己的子项目 spring-cloud-netflix 中,实现 SpringCloud 的服务发现功能。
在这里插入图片描述
上图简要描述了 Eureka 的基本架构,由 3 个角色组成:
1、Eureka Server

  • 提供服务注册和发现

2、Service Provider

  • 服务提供方
  • 将自身服务注册到 Eureka,从而使服务消费方能够找到

3、Service Consumer

  • 服务消费方
  • 从 Eureka 获取注册服务列表,从而能够消费服务

2.2 Eureka 的交互流程与原理

在这里插入图片描述
图是来自 Eureka 官方的架构图,大致描述了 Eureka 集群的工作过程。图中包含的组件非常多,解释一下:

  • Application Service 相当于服务提供者,Application Client 相当于服务消费者
  • Make Remote Call,可以简单理解为调用 RESTful API
  • us-east-1c、us-east-1d 等都是 zone,它们都属于 us-east-1 这个 region

关于 zone 和 region 的介绍可以看下这篇文章:eureka分区的深入讲解

由图可知,Eureka 包含两个组件:Eureka Server 和 Eureka Client,它们的作用如下:

  • Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互;
  • Eureka Server 提供服务发现的能力,各个微服务启动时,会通过Eureka Client 向 Eureka Server 进行注册自己的信息(例如网络信息),Eureka Server 会存储该服务的信息
  • 微服务启动后,会周期性地向 Eureka Server 发送心跳(默认周期 30 秒)以续约自己的信息。如果 Eureka Server 在一定时间内没有接收到某个微服务节点的心跳,Eureka Server 将会注销该微服务节点(默认 90 秒)
  • 每个 Eureka Server 同时也是 Eureka Client,多个 Eureka Server 之间通过复制的方式完成服务注册表的同步
  • Eureka Client 会缓存 Eureka Server 中的信息。即使所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者。

综上,Eureka 通过心跳检测、健康检查和客户端缓存等机制,提高了系统的灵活性、可伸缩性和可用性。

二、搭建 Eureka 注册中心

2.1 搭建 Eureka 服务中心

2.1.1 创建 cloud-eureka-server7001 子模块

在 cloud2020 下创建子模块 cloud-eureka-server7001

2.1.2 修改 pom.xml

<?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>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.springcloud</groupId>
    <artifactId>cloud-eureka-server7001</artifactId>
    <version>1.0-SNAPSHOT</version>


    <name>cloud-eureka-server7001</name>
    <dependencies>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--boot web actuator-->
        <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>
         <!-- 一般通用配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>
        </dependency>
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
</project>

2.1.3 配置 application.yml

server:
  port: 7001

eureka:
  instance:
    hostname: localhost  # eureka 服务端地实例名称
  client:
    register-with-eureka: false # false 表示不向注册中心注册自己
    fetch-registry: false # false 表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      # 设置与 Eureka Server 交互的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

register-with-eureka:是否将自己注册到 Eureka 服务中,本身就是所有无需注册
fetch-registry:是否从 Eureka 中获取注册信息
service-url:客户端与 Eureka 服务端进行交互的地址

2.1.4 配置启动类

创建启动类 EurekaMain7001

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
    public static void main( String[] args ) {
        SpringApplication.run(EurekaMain7001.class, args);
    }
}

@EnableEurekaServer:激活 Eureka Server 端的配置

2.1.5 测试

启动 EurekaMain7001,并访问 http://localhost:7001,即可进入 Eureka Sever 内置的管理控制台,显示效果如下:
在这里插入图片描述

2.2 服务 cloud-provider-payment8001 注册到 Eureka 注册中心

将 EurekaClient 端 cloud-provider-payment8001 注册进 EurekaServer ,使其成为服务提供者 provider

2.2.1 创建 cloud-provider-payment8001 子模块

在 cloud2020 下创建子模块 cloud-provider-payment8001

2.2.2 修改 pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.atguigu.springcloud</groupId>
        <artifactId>cloud2020</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provide-payment8001</artifactId>
    <dependencies>
        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </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>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>
         

2.2.3 配置 application.yml

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   # 当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver    # mysql 驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root


mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities  # 所有 Entity 别名类所在包
eureka:
  client:
    register-with-eureka: true  #表示是否将自己注册进EurekaServer,默认为true
    fetch-registry: true # 是否从 EurekaServer 抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://localhost:7001/eureka

2.2.4 配置主启动类 PaymentMain8001

创建启动类 PaymentMain8001

@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
    }

}

从 SpringCloud Edgware 版本开始,@EnableDiscoveryClient 或 @EnableEurekaClient 可以省略。只需加上相关依赖,并进行响应配置,即可将微服务注册到服务发现组件上。

2.2.5 业务代码

相关业务代码已在 SpringCloud 之微服务架构编码构建 中实现。

2.2.6 测试

测试前先将 EurekaServer 启动,然后再启动该子模块,都启动完成后,访问 http:localhost:7001
在这里插入图片描述

微服务注册名配置:
在这里插入图片描述

2.3 服务 cloud-consumer-order80 注册到 Eureka 注册中心

2.3.1 创建 cloud-consumer-order80 子模块

在 cloud2020 下创建子模块 cloud-consumer-order80

2.3.2 修改 pom.xml

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.atguigu.springcloud</groupId>
        <artifactId>cloud2020</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <artifactId>cloud-consumer-order80</artifactId>
    <name>cloud-consumer-order80</name>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </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>

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
          <scope>runtime</scope>
          <optional>true</optional>
        </dependency>
        <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <optional>true</optional>
        </dependency>
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
        </dependency>
    </dependencies>

</project>

2.3.3 配置 application.yml

server:
  port: 80
spring:
  application:
    name: cloud-order-service

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

2.3.4 配置主启动类

@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {

    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class, args);
    }

}

添加 @EnableEurekaClient,使该子模块成为 Eureka 客户端

2.3.5 测试

先要启动 EurekaServer(7001服务),再启动服务提供者 provider(8001 服务),最后启动该服务
在这里插入图片描述

三、搭建 Eureka Server 高可用集群

3.1 Eureka 工作流程

在这里插入图片描述

3.2 集群环境构建

3.2.1 新建 cloud-eureka-server7002 子模块

参照 cloud-eureka-server7002,新建 cloud-eureka-server7002

3.2.2 修改 pom.xml

<?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/maven-v4_0_0.xsd">
    <parent>
        <artifactId>cloud2020</artifactId>
        <groupId>com.atguigu.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-eureka-server7002</artifactId>
    <dependencies>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--boot web actuator-->
        <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>
        <!-- 一般通用配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </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>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
</project>

3.2.3 修改 host 文件

打开Finder,快捷键Shift+Command+G查找文件,输入/etc/hosts,然后回车进入
在这里插入图片描述
将 hosts 文件复制出来,使用文本编辑器打开,添加以下内容,并保存:

127.0.0.1  eureka7001.com
127.0.0.1  eureka7002.com

然后用修改后的 hosts 文件替换掉原先的文件。

3.2.3 修改 application.yml 文件

7001 服务:

server:
  port: 7001

eureka:
  instance:
    hostname: eureka7001.com  # eureka 服务端地实例名称
  client:
    register-with-eureka: false # false 表示不向注册中心注册自己
    fetch-registry: false # false 表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      # 设置与 Eureka Server 交互的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7002.com:7002/eureka/   # 将 7001 注册到 7002

7002 服务:

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/  # 将 7002 注册到 7001 

3.2.4 配置 7002 服务的主启动类

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7002 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7002.class, args);
    }
}

3.2.5 将支付微服务 8001 发布到上面 2 台 Eureka 集群配置中

修改 8001 微服务的 application.yml

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   # 当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver    # mysql 驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root


mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities  # 所有 Entity 别名类所在包
eureka:
  client:
    register-with-eureka: true  #表示是否将自己注册进EurekaServer,默认为true
    fetch-registry: true # 是否从 EurekaServer 抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版

3.2.6 将订单微服务 80 发布到上面 2 台 Eureka 集群配置中

修改 80 微服务的 application.yml

server:
  port: 80
spring:
  application:
    name: cloud-order-service

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版

3.2.8 测试01

先启动 EurekaServer(7001以及7002服务),再启动服务提供者 8001,最后启动服务消费者 80,然后访问 http://localhost/consumer/payment/get/31
在这里插入图片描述

3.2.6 构建支付服务集群环境

1、参考 cloud-provider-paymeng8001,新建 cloud-provider-paymeng8002
2、pom.xml 与 8001 一样,直接复制即可
3、修改 application.yml

server:
  port: 8002

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   # 当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver    # mysql 驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root


mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities  # 所有 Entity 别名类所在包
eureka:
  client:
    register-with-eureka: true  #表示是否将自己注册进EurekaServer,默认为true
    fetch-registry: true # 是否从 EurekaServer 抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版

4、配置 8002 服务的主启动类

@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8002 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8002.class, args);
    }

}

5、业务类与 8001 一致,直接复制即可

3.2.7 负载均衡

修改订单微服务的访问地址:

@RestController
@Slf4j
public class OrderController {

    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
//    public static final String PAYMENT_URL = "http://localhost:8001";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        return restTemplate.postForObject(PAYMENT_URL + "/payment/create", payment, CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public CommonResult<Payment> getPayment(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
    }
}

修改 ApplicationContextConfig,为 RestTemplate 增加 @LoadBalanced,赋予 RestTemplate 的负载均衡能力

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

3.2.8 测试02

先启动 EurekaServer(7001 以及 7002 服务),再启动服务提供者 provider(8001 以及 8002 服务),最后启动服务消费者 consumer(80 服务),然后访问 http://localhost/consumer/payment/get/31
在这里插入图片描述
在这里插入图片描述
8001 和 8002 端口交替出现,负载均衡效果实现

Ribbon 和 Eureka 整合后,Consumer 可以直接调用服务而不用关系服务地址和端口号,且该服务还具有了负载均衡功能。

四、actuator 微服务信息完善

4.1 服务名称修改

在这里插入图片描述
含有主机名称且将鼠标放置在服务名称上时,没有 ip 地址信息提示

4.2 修改 cloud-provider-paymeng8001

cloud-provider-paymeng8002 同 cloud-provider-paymeng8001 的修改方式一样

修改 application.yml
主要修改的内容:

eureka:
  client:
    register-with-eureka: true  #表示是否将自己注册进EurekaServer,默认为true
    fetch-registry: true # 是否从 EurekaServer 抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
  instance:
    instance-id: payment8001   # 显示名称
    prefer-ip-address: true  # 访问信息提示 IP 信息

增加了 instance

完整内容

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   # 当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver    # mysql 驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root


mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities  # 所有 Entity 别名类所在包
eureka:
  client:
    register-with-eureka: true  #表示是否将自己注册进EurekaServer,默认为true
    fetch-registry: true # 是否从 EurekaServer 抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
  instance:
    instance-id: payment8001   # 显示名称
    prefer-ip-address: true  # 访问信息提示 IP 信息

4.3 测试

在这里插入图片描述

五、服务发现 Discovery

可以通过服务发现来获取注册进 Eureka 里的微服务信息。

5.1 代码实现

1、修改 cloud-provider-payment8001 的 controller,注入 DiscoveryClient 类,并且编写 discovery 方法

@RestController
@Slf4j
@EnableDiscoveryClient
public class PaymentController {

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/paymeng/discovery")
    public Object discovery(){
        List<String> services = discoveryClient.getServices();
        for (String service : services) {
            log.info("*************service:" + service);
        }

        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance : instances) {
            log.info(instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
        }

        return discoveryClient;
    }
}

2、修改 8001 主启动类,添加注解 @EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8001 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class, args);
    }

}

5.2 测试

使用单机版 EurekaServer进行测试:
先启动 EurekaServer,再启动 8001 主启动类,然后访问 http://localhost:8001/payment/discovery
在这里插入图片描述
在这里插入图片描述

六、Eureka 自我保护机制

6.1 概述

保护模式主要用于一组客户端和 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  

在这里插入图片描述

6.2 Eureka 自我保护机制

为什么会产生 Eureka 自我保护机制?
Eureka服务端为了防止Eureka客户端本身是可以正常访问的,但是由于网路通信故障等原因,造成Eureka服务端失去于客户端的连接,从而形成的不可用。因为网络通信是可能恢复的,但是Eureka客户端只会在启动时才去服务端注册。如果因为网络的原因而剔除了客户端,将造成客户端无法再注册到服务端。

什么是自我保护?
默认情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例(默认 90 秒)。但是当网络分区发生故障(延时、卡顿、拥挤)时,微服务与 Eureka Server 之间无法正常通信,以上行为可能变得非常危险——因为微服务本身其实是健康的。此时本不应该注销这个微服务。Eureka 通过”自我保护模式“来解决这个问题——当 Eureka Server 节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
在这里插入图片描述
在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例。它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。

综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。使用自我保护模式,可以让 Eureka 集群更加的健壮、稳定。

6.3 关闭自我保护机制

6.3.1 注册中心 EurekaServer 端

自我保护机制默认是开启,可以在 application.yml 中进行配置,以关闭自我保护机制。使用 eureka.server.enable-self-preservation = false 可以禁用自我保护模式。

关闭 EurekaServer 端 7001 的自我保护机制:

server:
  port: 7001

eureka:
  instance:
    hostname: localhost  # eureka 服务端地实例名称
  client:
    register-with-eureka: false # false 表示不向注册中心注册自己
    fetch-registry: false # false 表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      # 设置与 Eureka Server 交互的地址,查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    enable-self-preservation: false  # 关闭自我保护机制

关闭后的效果如下:
在这里插入图片描述

6.3.2 生产者客户端 EurekaClient 端

可以在 application.yml 中进行配置,配置命令如下:

# 客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
eureka.instance.lease-renewal-interval-in-seconds: 30  
# 服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除
eureka.instance.lease-expiration-duration-in-seconds: 90 

修改生产者 8001 的 application.yml:

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource   # 当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver    # mysql 驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: root


mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities  # 所有 Entity 别名类所在包
eureka:
  client:
    register-with-eureka: true  #表示是否将自己注册进EurekaServer,默认为true
    fetch-registry: true # 是否从 EurekaServer 抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true,才能配合ribbon使用负载均衡
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: payment8001
    prefer-ip-address: true
    # 客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
    lease-renewal-interval-in-seconds: 1  
    # 服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除
    lease-expiration-duration-in-seconds: 2 

6.3.3 测试

7001 和 8001 都配置完成后,先将 7001 启动,再启动 8001,随后关闭 8001。

未关闭 8001 前:
在这里插入图片描述
关闭后,8001 会被立刻删除:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值