2021升级版SpringCloud教程从入门到实战精通「H版&alibaba&链路追踪&日志&事务&锁」

教程全目录「含视频」https://gitee.com/bingqilinpeishenme/Java-Wiki

Eureka服务注册和发现

本文要点:

  • 什么是服务注册和发现
  • Eureka的使用
  • CAP
  • Eureka集群搭建

什么是服务注册和发现

1593934895413

  • 治理中心
  • 服务注册
  • 服务发现
  • 心跳机制

以上都可以通过 Eureka 可以实现

Eureka基本使用

基本概念

Spring Cloud 封装了 Netflix 公司开发的 Eureka 组件来实现服务注册和发现。

image-20200420161934202

在Eureka的架构中有两个角色:服务注册中心 Eureka Server服务客户端 Eureka Client

  • Eureka注册中心 Eureka Server

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

  • Eureka客户端 Eureka Client

    EurekaClient是一个Java客户端,用于简化Eureka Server的交互

    • 在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
    • Eureka Client会缓存服务注册表中的信息。这种方式有一定的优势首先可以降低Eureka Server的压力,其次当所有的Eureka Server宕机,服务调用方依然可以完成调用

Eureka注册中心搭建

  1. 在Project中创建module

    image-20210109160624673

  2. 导入依赖

      <!--        引入SpringCloud Eureka server的依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
  3. 启动类上加注解

    1593935968864

  4. 配置文件

    server:
      port: 8800
    
    eureka:
      client:
        #    eureka.client. register-with-eureka:由于该应用为注册中心,所以设置为false,代表不向注册中心注册自己
        registerWithEureka: false
        #      不主动发现别人
        fetchRegistry: false
        #    声明注册中心的地址
        serviceUrl:
          defaultZone: http://localhost:8800/eureka/
    
    #给当前应用起个服务名称 不能通过路径访问的  这个服务名称 在微服务中使用代表当前服务
    spring:
      application:
        name: eureka-server
  5. 启动注册中心 访问注册中心的监控页面 http://localhost:8800

    image-20210109160155304

客户端搭建—用户服务

以用户服务为例

  1. 创建项目

    image-20200420164741922

  2. 导入相关依赖

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
  3. 启动类上加注解

    image-20200420165233554

  4. 配置文件

    server:
      port: 8804
    
    #指定当前服务的名称  这个名称会注册到注册中心
    spring:
      application:
        name: cloud-user-8804
    
    #  指定 服务注册中心的地址
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8800/eureka

通过以上四步 就完成了一个 Eureka客户端的搭建 直接启动项目 通过Eureka的注册中心可以看到

image-20210109160221422

按照上述步骤,将商品服务和订单服务改造为Eureka客户端。

Eureka进阶使用

CAP理论

目前,大型网站几乎都是分布式的,分布式系统的最大难点,就是各个节点的状态如何同步。CAP 定理是这方面的基本定理,也是理解分布式系统的起点。

1998年,加州大学的计算机科学家 Eric Brewer 提出,分布式系统有三个指标。

  • Consistency 一致性
  • Availability 可用性
  • Partition tolerance 分区容错性

它们的第一个字母分别是 C、A、P。

Eric Brewer 说,这三个指标不可能同时做到。这个结论就叫做 CAP 定理。

  • 分区容错性

    大多数分布式系统都分布在多个子网络。每个子网络就叫做一个区(partition)。分区容错的意思是,区间通信可能失败。比如,一台服务器放在中国,另一台服务器放在美国,这就是两个区,它们之间可能无法通信。

    Node1 和 Node2 是两台跨区的服务器。Node1 向 Node2 发送一条消息,Node2可能无法收到。系统设计的时候,必须考虑到这种情况。

    一般来说,分区容错无法避免,因此可以认为 CAP 的 P 总是成立。CAP 定理告诉我们,剩下的 C 和 A 无法同时做到。

  • 数据一致性

    由于系统问题,Node1 的数据不能即时同步给Node2,此时如果获取数据,会获取到不一致的数据,所有为了保证分布式系统对外的数据一致性,选择不返回任何数据【或者所有节点不响应任何请求】。

  • 可用性

    要求系统内的节点在接受到请求的时候能够即时给出响应,具体来说就是:一方面需要在合理的时间内给出响应,另一方面即便是部分节点宕机,那么其他未宕机的节点也需要能够正常处理请求,即时返回的数据有问题。

一致性和可用性,为什么不可能同时成立?

答案很简单,因为可能通信失败(即出现分区容错),所以,对于分布式系统,我们只能能考虑当发生分区错误时,如何选择一致性和可用性。

需要强调的是:C 和 A 的抉择是发生在有分区问题的时候,正常情况下系统就应该有完美的数据一致性和可用性

例子:

比如,我们有个分布式系统,由三个节点 a、b、c 组成。其中节点 a 存放了 A 表的数据,b 存放了 B 表的数据,c 存放了 C 表的数据。

如果有一个业务,它的意图是想往 A 表插入一条新数据,在 B 表删除一条已有数据,在 C 表更新一条老数据,这个分布式系统该怎么处理这种业务?

技术上我们对这种一个意图想做多件事的情况往往会包装成一个事务。当我们包装成一个事务以后,我们可能会通过先在 a 节点执行,然后去 b 节点执行,最后去 c 节点执行,等到都成功了,才会返回成功。

但是,发生了分区以后怎么办?当在 a、b 节点都成功了,到 c 发现发生了通信故障?

此时,根据 CAP 定理,你有两个选择,要么就直接返回一个部分成功的结果给客户端,要么直接卡死等客户端超时或者返回失败给客户端。当返回部分成功的时候,这就是选择了可用性(A),当卡死或者返回失败给客户端的时候,就是选择了一致性(C)。

而根据一致性和可用性的选择不同,开源的分布式系统往往又被分为 CP 系统和 AP 系统。

  • 当一套系统在发生分区故障后,客户端的任何请求都被卡死或者超时,但是,系统的每个节点总是会返回一致的数据,则这套系统就是 CP 系统,经典的比如 Zookeeper。
  • 如果一套系统发生分区故障后,客户端依然可以访问系统,但是获取的数据有的是新的数据,有的还是老数据,那么这套系统就是 AP 系统,经典的比如 Eureka。
很多时候一致性和可用性并不是二选一的问题,大部分的时候,系统设计会尽可能的实现两点,在二者之间做出妥协,当强调一致性的时候,并不表示可用性是完全不可用的状态,比如,Zookeeper 只是在 master 出现问题的时候,才可能出现几十秒的不可用状态,而别的时候,都会以各种方式保证系统的可用性。而强调可用性的时候,也往往会采用一些技术手段,去保证数据最终是一致的。

自我保护机制

Eureka首页输出警告如图:

image-20210109160302395

默认情况下,如果Eureka Server在一定时间内没有接受到服务实例的心跳,Eureka将会注销该实例(默认90秒).但是当网络分区发生故障时,微服务客户端和Eureka Server 无法正常通信。以上行为可能变得特别危险了,因为微服务本身是健康的,此时不能注销该服务实例。

Eureka通过自我保护机制来解决这个问题,当Eureka Server在短时间丢失过多的服务实例(可能发生了网络分区的故障),那么Eureka Server进入自我保护模式,一旦进入此模式,Eureka Server将会保护服务注册表中的信息,不再删除服务注册表中的数据(也就是不再注销任何的服务实例),当网络故障恢复后,Eureka Server会自动退出自我保护模式。

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

一句话:大面积出现客户端失联的时候,Eureka 注册中心进入自我保护模式,不注销任何实例
自我保护机制的配置【了解】

在Eureka Server中配置关闭自我保护机制

#关闭自我保护机制  默认开启
eureka.server.enable-self-preservation=false

如果想及时剔除失效的eureka服务除了关闭自我保护机制外,可以调低eureka的心跳值

eureka-server服务端
配置文件中我们添加如下配置

#关闭保护机制,以确保注册中心将不可用的实例正确剔除
eureka.server.enable-self-preservation=false
#(代表是5秒,单位是毫秒,清理失效服务的间隔 )
eureka.server.eviction-interval-timer-in-ms=5000
客户端
配置文件中我们添加如下配置

# 心跳检测检测与续约时间
# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务
# 配置说明
#  lease-renewal-interval-in-seconds 每间隔10s,向服务端发送一次心跳,证明自己依然”存活“
#  lease-expiration-duration-in-seconds  告诉服务端,如果我20s之内没有给你发心跳,就代表我“死”了,将我踢出掉。
eureka.instance.lease-renewal-interval-in-seconds=10
eureka.instance.lease-expiration-duration-in-seconds=20

Eureka集群搭建

注册中心集群,防止注册中心单机故障。

  1. 创建一个新的注册中心 eureka-server-8801

    1. 创建项目

      image-20210109160323741

    2. 导入依赖
    3. 启动类加注解
    4. 写配置文件

      image-20210109160336831

  2. 修改注册中心 Eureka-server-8800的配置文件

    image-20210109160350052

  3. 修改所有的客户端的配置,让客户端能够同时向两个注册中心注册

    image-20210109160405439

  4. 启动所有的客户端和注册中心 看看能不能正常注册

如果你觉得这篇内容对你挺有有帮助的话:

  1. 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)
  2. 欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。
  3. 觉得不错的话,也可以关注 编程鹿 的个人公众号看更多文章和讲解视频(感谢大家的鼓励与支持🌹🌹🌹)


鹿老师的Java笔记
111 声望34 粉丝