SpringCloud 学习笔记(2)- Eureka 服务注册与发现

文章目录

1、Eureka 基础知识

1.1、什么是服务治理?

Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务治理。

在传统的 RPC 远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用负载均衡容错等,实现服务发现与注册

1.2、什么是服务注册与发现?

Eureka 采用了 CS 的设计架构,Eureka Sever 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Sever 并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行。

在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器的信息比如:服务地址通讯地址等以别名方式注册到注册中心上。另一方(消费者服务提供者),以该别名的方式去注册中心上获取到实际的服务通讯地址,然后再实现本地 NPC 调用 RPC 远程调用框架。

核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一个依赖关系(服务治理概念)。在任何 RPC 远程框架中,都会有一个注册中心(存放服务地址相关信息(接口地址))。

在这里插入图片描述

1.3、Eureka 两大组件

Eureka Server 提供服务注册服务

各个微服务节点通过配置启动后,会在 Eureka Server 中进行注册,这样 Eureka Server 中的服务注册表中将会存储所有可用服务节点信息,服务节点的信息可以在界面中直观看到。

Eureka Client 通过注册中心进行访问

是一个 Java 客户端,用于简化与 Eureka Server 的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向 Eureka Server 发送心跳(默认周期为 30 秒)。如果 Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个服务节点移除(默认 90 秒)。

2、单机 Eureka 构建步骤

2.1、建立 cloud-eureka-server7001 模块

查看父 pom

<!-- 模块说明:这里声明多个子模块 -->
<modules>
    <module>cloud-provider-payment8001</module>
    <module>cloud-consumer-order80</module>
    <module>cloud-api-commons</module>
    <!-- 新加入的模块 -->
    <module>cloud-eureka-server7001</module>
</modules>

2.2、更改 pom 文件

以前老版本(2018)

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

现在新版本(2020.2)

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

更改 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>springcloud-parent</artifactId>
        <groupId>com.springcloud-demo</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-eureka-server7001</artifactId>

    <dependencies>

        <!-- eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        
        <!-- 引入自己定义的 api 通用包 -->
        <dependency>
            <groupId>com.springcloud-demo</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <!-- web -->
        <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-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 热部署 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>

</project>

2.3、写 YML

server:
  port: 7001

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

2.4、主启动类(新建)

注意:@EnableEurekaServer

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {

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

2.5、测试

http://localhost:7001/

在这里插入图片描述

3、EurekaClient 端

3.1、将 cloud-provider-payment8001 注册进 Eureka Server 成为服务提供者 provider

3.1.1、更改 pom 文件(cloud-provider-payment8001)

以前老版本(2018)

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

现在新版本(2020.2)

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

更改 pom 文件

<!-- eureka-client -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.1.2、写 YML(添加)
eureka:
  client:
    # 表示是否将自己注册进 Eureka Server, 默认为 true
    register-with-eureka: true
    # 是否从 Eureka Server 抓取已有的注册信息, 默认为 true, 集群必须设置为 true 才能配合 Ribbon 实现负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka
3.1.3、主启动(修改)

注意:@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class);
    }
}
3.1.4、测试

先要(重新)启动 EurekaServer,不然会触发保护机制

http://localhost:7001/
在这里插入图片描述

微服务注册名配置说明

在这里插入图片描述

3.1.5、自我保护机制

在这里插入图片描述

3.2、将 cloud-consumer-order80 注册进 Eureka Server 成为服务消费者 consumer

3.2.1、更改 pom 文件(cloud-consumer-order80)
<!-- eureka-client -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3.2.2、写 YML(添加)
eureka:
  client:
    # 表示是否将自己注册进 Eureka Server, 默认为 true
    register-with-eureka: true
    # 是否从 Eureka Server 抓取已有的注册信息, 默认为 true, 集群必须设置为 true 才能配合 Ribbon 实现负载均衡
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka
3.2.3、主启动(修改)

注意:@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class OrderMain {

    public static void main(String[] args) {
        SpringApplication.run(OrderMain.class);
    }
}
3.2.4、测试
  • 先要(重新)启动 Eureka Server,7001 服务
  • 再启动服务提供者 provider,8001 服务

http://localhost:7001/
在这里插入图片描述
在这里插入图片描述

4、集群 Eureka 构建步骤

4.1、Eureka 集群原理说明

在这里插入图片描述

问题:微服务 RPC 远程服务调用最核心的是什么?

高可用,试想你的注册中心只有一个,它如果出故障了会导致整个为服务环境不可用。

解决办法

搭建 Eureka 注册中心集群,实现负载均衡 + 故障容错。

4.2、Eureka Server 集群环境构建步骤

4.2.1、参考 cloud-eureka-server7001,新建 cloud-eureka-server7002
4.2.2、更改 pom 文件(cloud-eureka-server7002)
4.2.3、修改映射配置
  • 找到 C:\Windows\System32\drivers\etc 路径下的 hosts 文件
    在这里插入图片描述
  • 修改映射配置添加进 hosts 文件
    • 127.0.0.1 eureka7001.com
    • 127.0.0.1 eureka7002.com
      在这里插入图片描述
4.2.4、修改 YML(以前单机)
  1. 7001
server:
  port: 7001

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

spring:
  application:
    name: eureka-server
eureka:
  instance:
    hostname: eureka7002.com  # eureka 服务端的实例名字
  client:
    register-with-eureka: false # 标识不向注册中心注册自己
    fetch-registry: false  # 表示自己就是注册中心, 职责是维护服务实例, 并不需要去检索服务
    service-url:
      # 设置与 eureka server 交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://eureka7001.com:7001/eureka/
4.2.5、主启动

主启动(复制 cloud-eureka-server7001 的主启动类到 7002 即可)

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

修改 YML

service-url:
  defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
4.2.7、将订单服务 80 微服务发布到上面 2 台 Eureka 集群配置中
service-url:
  defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka  # 集群版
4.2.8、测试
  1. 先要启动 Eureka Server,7001/7002 服务
  2. 再要启动服务提供者 provider,8001 服务
  3. 再要启动消费者,80 服务

http://eureka7001.com:7001/
在这里插入图片描述

http://eureka7002.com:7002/
在这里插入图片描述

http://localhost/consumer/listPayment
在这里插入图片描述

4.3、支付服务提供者 8001 集群环境构建

4.3.1、参考 cloud-provider-payment8001,新建 cloud-provider-payment8002
4.3.2、更改 pom 文件(cloud-provider-payment8002)
4.3.3、修改 YML
server:
  port: 8002
4.3.4、主启动

主启动(复制 cloud-provider-payment8001 的主启动类到 8002 即可)

4.3.5、修改 8001/8002 的 Controller

在这里插入图片描述

4.3.6、测试

在这里插入图片描述

在这里插入图片描述

4.3.7、负载均衡

订单服务访问地址不能写死
在这里插入图片描述

使用 @LoadBalanced 注解赋予 RestTemplate 负载均衡的能力
在这里插入图片描述

4.3.8、测试
  1. 先要启动 Eureka Server,7001/7002 服务
  2. 再要启动服务提供者 provider,8001 服务
  3. 再要启动消费者,80 服务
  4. 用 Postman 访问 http://localhost/consumer/listPayment 测试

测试结果

  • 负载均衡效果达到
  • 8001/8002 端口服务交替执行
  • Ribbon 和 Eureka 整合后 Consumer 可以直接调用服务而不用再关心地址和端口号,且该服务还有负载功能了

5、actuator 微服务信息完善

5.1、主机名称:服务名称修改(不暴露主机名称)

  1. cloud-provider-payment8001
    在这里插入图片描述
  2. cloud-provider-payment8002
    在这里插入图片描述

结果

在这里插入图片描述

5.2、访问信息有 IP 信息提示

  1. cloud-provider-payment8001
    在这里插入图片描述
    1. cloud-provider-payment8002
      在这里插入图片描述

结果

在这里插入图片描述

6、服务发现 Discovery

对于注册进 Eureka 里面的微服务,可以通过服务发现来获得该服务的信息

  1. 修改 cloud-provider-payment8001/8002 的 controller,添加如下代码
/**
 * import org.springframework.cloud.client.discovery.DiscoveryClient;
 */
@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/discovery")
public Object discovery() {
    List<String> services = discoveryClient.getServices();
    for (String service : services) {
        log.info("************Application : {}", 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 this.discoveryClient;
}
  1. 8001 主启动类 @EnableDiscoveryClient

在这里插入图片描述

测试

先要启动 EurekaServer,7001/7002 服务
再启动 8001 主启动类,需要稍等一会

http://localhost:8001/discovery
在这里插入图片描述

7、Eureka 自我保护

7.1、概述

保护模式主要用于一组客户端和 Eureka Server 之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server 将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。

如果在 Eureka Server 的首页看到以下这段提示,则说明 Eureka 进入了保护模式:
在这里插入图片描述

7.2、导致原因

一句话:某时刻某一个微服务不可用了,Eureka 不会立刻清理,依旧会对该微服务的信息进行保存。

属于 CAP 里面的 AP 分支。

7.2.1、为什么会产生 Eureka 自我保护机制?

为了防止 Eureka Client 可以正常运行,但是与 Eureka Server 网络不通情况下,Eureka Server 不会立刻将 Eureka Client 服务剔除。

7.2.2、什么是自我保护模式?

默认情况下,如果 Eureka Server 在一定时间内没有接收到某个微服务实例的心跳,Eureka Server 将会注销该实例(默认90秒)。

但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与 Eureka Server 之间无法正常通信,以上行为可能变得非常危险了 —— 因为微务本身其实是健康的,此时本不应该注销这个微服务。

Eureka 通过 “自我保护模式” 来解决这个问题 —— 当 Eureka Server 节点在时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。

在自我保护模式中,Eureka Server 会保护服务注册表中的信息,不再注销任何服务实例。

它的设计哲学就是宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。

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

使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

7.3、怎么禁止自我保护?(一般生产环境中不会禁止自我保护)

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值