Eureka


一 什么是SpringCloud?

Author:呆萌老师 QQ:2398779723 微信:it_daimeng

Spring Cloud是一个微服务框架,相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案,是若干个框架的集合。

Spring Cloud为微服务架构开发涉及的配置管理,服务治理,熔断机制,智能路由,微代理,控制总线,一次性token,全局一致性锁,leader选举,分布式session,集群状态管理等操作提供了一种简单的开发方式。

Spring Cloud 为开发者提供了快速构建分布式系统的工具,开发者可以快速的启动服务或构建应用、同时能够快速和云平台资源进行对接。

二 SpringCloud结构

SpringCloud包含了很多子项目:

在这里插入图片描述

  • Spring Cloud Config:配置管理工具,支持使用Git存储配置内容,支持应用配置的外部化存储,支持客户端配置信息刷新、加解密配置内容等

  • Spring Cloud Bus:事件、消息总线,用于在集群(例如,配置变化事件)中传播状态变化,可与Spring Cloud Config联合实现热部署。

  • Spring Cloud Netflix:针对多种Netflix组件提供的开发工具包,其中包括Eureka、Hystrix、Zuul、Archaius等。

    ​ Netflix Eureka:一个基于rest服务的服务治理组件,包括服务注册中心、服务注册与服务发现机制的实现,实现了云端负载均衡和中间层服务器的故障转移。

    ​ Netflix Hystrix:容错管理工具,实现断路器模式,通过控制服务的节点,从而对延迟和故障提供更强大的容错能力。

    ​ Netflix Ribbon:客户端负载均衡的服务调用组件。

    ​ Netflix Feign:基于Ribbon和Hystrix的声明式服务调用组件。

    ​ Netflix Zuul:微服务网关,提供动态路由,访问过滤等服务。

    ​ Netflix Archaius:配置管理API,包含一系列配置管理API,提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。

  • Spring Cloud for Cloud Foundry:通过Oauth2协议绑定服务到CloudFoundry,CloudFoundry是VMware推出的开源PaaS云平台。

  • Spring Cloud Sleuth:日志收集工具包,封装了Dapper,Zipkin和HTrace操作。

  • Spring Cloud Data Flow:大数据操作工具,通过命令行方式操作数据流。

  • Spring Cloud Security:安全工具包,为你的应用程序添加安全控制,主要是指OAuth2。

  • Spring Cloud Consul:封装了Consul操作,consul是一个服务发现与配置工具,与Docker容器可以无缝集成。

  • Spring Cloud Zookeeper:操作Zookeeper的工具包,用于使用zookeeper方式的服务注册和发现。

  • Spring Cloud Stream:数据流操作开发包,封装了与Redis,Rabbit、Kafka等发送接收消息。

  • Spring Cloud CLI:基于 Spring Boot CLI,可以让你以命令行方式快速建立云组件。

二 服务的注册与发现–Eureka

1.Eureka介绍

Eureka是spring cloud中的一个负责服务注册与发现的组件。

一个Eureka中分为eureka server和eureka client。其中eureka server是作为服务的注册与发现中心。eureka client既可以作为服务的生产者(服务注册),又可以作为服务的消费者(服务发现)。

如图所示:

在这里插入图片描述

基本原理:

服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。

2.Eureka服务注册和发现

Eureka使用需要服务器端和客户端,他们都需要使用到SpringCloud版本,所以这里我们使用maven父子工程来处理。

2.1 创建父工程

创建一个最简单的SpringBoot项目

在这里插入图片描述

修改pom.xml文件

添加版本管理器,添加SpringCloud版本,子项目里就不用设置版本号了,将pom文件中的dependencies和build删除,只需要这些:

<!-- springcloud版本 只是对版本进行管理,不会实际引入jar -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2020.0.3</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

修改packaging的类型为pom,代表父工程只有pom文件

<!-- 父类型都为pom类型 -->
<packaging>pom</packaging>

父工程中的src等文件夹也可以删除

2.2 创建Eureka的服务器端

在父工程上右键->new Module–>选择maven–>next
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

输入子工程的名字

在pom文件中添加jar包

<dependencies>
    <!-- eureka-server需要的jar包  版本号不需要设置 因为父工程中已经设置 -->
    <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>

</dependencies>

创建项目入口类,并添加启动EurekaServer的注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pc1yc7L2-1668090783798)(pic/9.png)]

创建application.yml文件

添加配置信息

server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

此配置信息可以在官网中获取:
在这里插入图片描述

在这里插入图片描述

启动测试:

在这里插入图片描述

浏览器中输入http://localhost:8761访问,出来以下页面代表成功
在这里插入图片描述

2.3 服务注册

创建子工程2作为Eureka的Client端

创建一个子工程,方法同上

在这里插入图片描述

添加jar包

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

</dependencies>

创建SpringBoot项目入口类,并添加EurekaClient注解

在这里插入图片描述

添加配置信息

在这里插入图片描述

测试:

启动客户端,刷新服务器端地址,可以看到服务USERS已注册到服务器端

在这里插入图片描述

2.4.服务发现

1.再创建一个客户端

创建子工程3作为Eureka的另一个Client端,添加

方法同上

添加jar包

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

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

</dependencies>

创建SpringBoot项目入口类,并添加EurekaClient注解

在这里插入图片描述

添加配置信息,注意修改一下端口号,避免和eureka_02冲突

在这里插入图片描述

2.在客户端2中添加一个查询方法

在这里插入图片描述

3.在客户端1中调用客户端1中的方法

在这里插入图片描述

4.测试

重启服务器和两个客户端

测试:

在这里插入图片描述

在这里插入图片描述

3.给Eureka添加安全验证

Author:呆萌老师 QQ:2398779723 微信:it_daimeng

在生产环境上,如果任何人输入地址直接就可以进入到Eureka服务治理界面,这样很容易被别人盗取信息,非常不安全。所以我们需要给Eureka添加安全验证。

给Eureka添加安全验证,可以使用Spring Security来实现。

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架(简单说是对访问权限进行控制嘛)。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

3.1在Eureka服务器端添加安全验证

1.在Eureka服务器端添加jar包
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.在Eureka服务器端application.yml文件中添加登录的用户名和密码
spring:
  security:
    user:
      name: root
      password: 123

在这里插入图片描述

3.重启服务器,测试

在这里插入图片描述

可以看到有登录页面了。

3.2Eureka客户端如何通过安全验证访问服务器端

在Eureka服务端,我们加入了Spring Security,而 Spring Cloud 2.0 以上的security默认启用了csrf检验,所以我们需要在eurekaServer端的csrf检验中过滤掉Eureka客户端的路径,否则服务无法注册进 eureka注册中心。

1.在Eureka服务端添加配置类
package com.test.eureka.config;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

//注意添加注解
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

        protected  void configure(HttpSecurity httpSecurity) throws Exception {

               //让csrf忽略eureka路径 不做csrf验证
              httpSecurity.csrf().ignoringAntMatchers("/eureka/**");
              super.configure(httpSecurity);
        }
}

在这里插入图片描述

2.在客户端设置的服务器地址上添加验证信息

在这里插入图片描述

3.测试

重新启动客户端

刷新Eureka服务管理页面,可以看到注册进去了

在这里插入图片描述

4.搭建Eureka集群实现高可用

Author:呆萌老师 QQ:2398779723 微信:it_daimeng

我们前面搭建的Eureka服务器是单节点的,如果这个点发生故障,整个服务就会瘫痪,称为单点故障,所以我们需要搭建成集群,一个点出问题,还有另一个点顶上去,代替这个点工作,从而实现高可用、高性能。

实现原理:

在Eureka高可用架构中,Eureka Server也可以作为Client向其他server注册,多节点相互注册组成Eureka集群,集群间相互视为peer(同行)。Eureka Client向Server注册、续约、更新状态时,接收节点更新自己的服务注册信息后,逐个同步至其他peer节点

4.1 再创建一个Eureka服务器端

配置信息稍有不同,其它都一样。

在这里插入图片描述

在这里插入图片描述

启动两台服务器:

因为前面设置了将自己注册进去,所以可以看到各自都有自己的服务器

在这里插入图片描述

在这里插入图片描述

4.2 给客户端添加两个服务器的地址

修改两个客户端的配置文件,将两个服务器地址都加上

在这里插入图片描述

启动客户端后,查看服务注册中心页面:

会发现两个客户端都只在一个服务器中出现,可能是8761也可能是8762

在这里插入图片描述

在这里插入图片描述

4.3设置两台服务器之间相互通讯

修改两个服务器的配置信息

在这里插入图片描述

在这里插入图片描述

重新启动两个服务器,因为需要用到对方服务器,所以一次重启一个,不要同时重启。

可以看到两个服务器中都有注册的服务了。

在这里插入图片描述

在这里插入图片描述

4.4测试一台服务器宕机的情况

访问某一个服务:

在这里插入图片描述

将其中的一台服务器关闭,仍然可以访问。这样就实现了高可用。

在这里插入图片描述

5.Eureka的缓存机制

从CAP理论看,Eureka是一个AP系统,优先保证可用性(A)和分区容错性§,不保证强一致性©,只保证最终一致性,因此在架构中设计了较多缓存。

5.1Eureka Server缓存机制

Eureka Server存在三个变量:(registry、readWriteCacheMap、readOnlyCacheMap)保存服务注册信息。

写操作

包括注册、取消注册等,都直接操作在registry上,同时也会更新recentlyChangedQueue和readWriterCacheMap

读操作

读默认是从readOnlyCacheMap读取,读不到的话再从readWriterCacheMap,还是没有再从registry。默认情况下定时任务每30s将readWriteCacheMap同步至readOnlyCacheMap。每60s清理超过90s未续约的节点。

Eureka Client每30s从readOnlyCacheMap更新服务注册信息,而UI则从registry更新服务注册信息。

三级缓存

缓存类型说明
registry ConcurrentHashMap 实时更新,类AbstractInstanceRegistry成员变量,UI端请求的是这里的服务注册信息
readWriteCacheMap Guava Cache/LoadingCache 实时更新,类ResponseCacheImpl成员变量,缓存时间180秒
readOnlyCacheMap ConcurrentHashMap 周期更新,类ResponseCacheImpl成员变量,默认每30s从readWriteCacheMap更新,Eureka client默认从这里更新服务注册信息,可配置直接从readWriteCacheMap更新

缓存相关配置

配置默认说明
eureka.server.useReadOnlyResponseCache true Client从readOnlyCacheMap更新数据,false则跳过readOnlyCacheMap直接从readWriteCacheMap更新
eureka.server.responsecCacheUpdateIntervalMs 30000 readWriteCacheMap更新至readOnlyCacheMap周期,默认30s
eureka.server.evictionIntervalTimerInMs 60000 清理未续约节点(evict)周期,默认60s
eureka.instance.leaseExpirationDurationInSeconds 90 清理未续约节点超时时间,默认90s

关键类

类名说明
com.netflix.eureka.registry.AbstractInstanceRegistry 保存服务注册信息,持有registry和responseCache成员变量
com.netflix.eureka.registry.ResponseCacheImpl 持有readWriteCacheMap和readOnlyCacheMap成员变量

5.2 Eureka Client缓存机制

Eureka Client 启动时会全量拉取服务列表,启动后每隔 30 秒从 Eureka Server 量获取服务列表信息,并保持在本地缓存中。

服务调用时,客户端会先从本地缓存找到调用服务,如果调取不到 先从注册中心刷新注册表,再同步到本地

二级缓存

缓存类型说明
localRegionApps AtomicReference 周期更新,类DiscoveryClient成员变量,Eureka Client保存服务注册信息,启动后立即向Server全量更新,默认每30s增量更新
upServerListZoneMap ConcurrentHashMap 周期更新,类LoadBalancerStats成员变量,Ribbon保存使用且状态为UP的服务注册信息,启动后延时1s向Client更新,默认每30s更新

缓存相关配置

配置默认说明
eureka.instance.leaseRenewalIntervalInSeconds 30 Eureka Client 续约周期,默认30s
eureka.client.registryFetchIntervalSeconds 30 Eureka Client 增量更新周期,默认30s(正常情况下增量更新,超时或与Server端不一致等情况则全量更新)
ribbon.ServerListRefreshInterval 30000 Ribbon 更新周期,默认30s

关键类

类名说明
com.netflix.discovery.DiscoveryClient Eureka Client 负责注册、续约和更新,方法initScheduledTasks()分别初始化续约和更新定时任务
com.netflix.loadbalancer.PollingServerListUpdater Ribbon 更新使用的服务注册信息,start初始化更新定时任务
com.netflix.loadbalancer.LoadBalancerStats Ribbon,保存使用且状态为UP的服务注册信息

同时对于服务调用,如果涉及到 ribbon 负载均衡,那么 ribbon 对于这个实例列表也有自己的缓存,这个缓存定时(默认30秒)从 Eureka Client 的缓存更新。

5.3 缓存问题

这么多的缓存机制可能就会造成一些问题,一个服务启动后可能最长需要 90s 才能被其它服务感知到:

1、首先,Eureka Server 维护每 30s 更新的响应缓存

2、Eureka Client 对已经获取到的注册信息也做了 30s 缓存

3、负载均衡组件 Ribbon 也有 30s 缓存

这三个缓存加起来,就有可能导致服务注册最长延迟 90s ,这个需要我们在特殊业务场景中注意其产生的影响

在生产环境下,我们可以修改Eureka Client缓存的定期更新周期:

eureka.client.registryFetchIntervalSeconds默认30秒,可以修改,比如设置为5秒。

在这里插入图片描述

还可以禁用readOnlyCacheMap,直接从readWriteCacheMap获取服务列表。

eureka.server. useReadOnlyResponseCache=false

6.Eureka心跳机制

Author:呆萌老师 QQ:2398779723 微信:it_daimeng

6.1原理

  1. 服务器启动成功,等待客户(服务)端注册,在启动过程中如果我们配置了集群,集群之间会同步注册表,每一个Eureka serve都会存在这个集群完整的服务注册表信息
  2. Eureka client 启动时根据配置信息,去注册到指定的注册中心
  3. Eureka client会每30秒向Eureka server 发送一次心跳请求,证明该客户端服务正常
  4. 当Eureka server90s内没有接受客户端服务正常,注册中心会认为该节点失效,会注销该实列 (从注册表中删除注册信息)
  5. 单位时间内如果服务端统计到大量客户端没有发送心跳,则认为网络异常,进去自我保护机制,不在剔除没有发送心跳的客户端
  6. 当客户端恢复正常之后,服务端就会退出自我保护模式

6.2 心跳设置

eureka: 
  instance:
    #eureka客户端需要多长时间发送心跳给eureka服务器,表明他仍然或者,默认30秒
    lease-renewal-interval-in-seconds: 5
    #eureka服务器在接受到实力的最后一次发出的心跳后,需要等待多久才可以将此实力删除
    lease-expiration-duration-in-seconds: 10

7.Eureka自我保护机制

Author:呆萌老师 QQ:2398779723 微信:it_daimeng

默认情况下,如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制。

自我保护模式正是一种针对网络异常波动的安全保护措施,使用自我保护模式能使Eureka集群更加的健壮、稳定的运行。

7.1工作机制

自我保护机制的工作机制是如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制,此时会出现以下几种情况:

1、Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。

2、Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。

3、当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中。

因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况,而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪。

7.2自我保护开关

Eureka自我保护机制,通过配置eureka.server.enable-self-preservation来true打开/false禁用自我保护机制,默认打开状态,建议生产环境打开此配置。

7.3开发环境配置

开发环境中如果要实现服务失效能自动移除,只需要修改以下配置。

1、注册中心关闭自我保护机制,修改检查失效服务的时间。
eureka:
  server: 
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 3000
2、微服务修改减短服务心跳的时间。
# 默认90秒
lease-expiration-duration-in-seconds: 10
# 默认30秒
lease-renewal-interval-in-seconds: 3

上,保证当前节点依然可用。

3、当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中。

因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况,而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪。

7.2自我保护开关

Eureka自我保护机制,通过配置eureka.server.enable-self-preservation来true打开/false禁用自我保护机制,默认打开状态,建议生产环境打开此配置。

7.3开发环境配置

开发环境中如果要实现服务失效能自动移除,只需要修改以下配置。

1、注册中心关闭自我保护机制,修改检查失效服务的时间。
eureka:
  server: 
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 3000
2、微服务修改减短服务心跳的时间。
# 默认90秒
lease-expiration-duration-in-seconds: 10
# 默认30秒
lease-renewal-interval-in-seconds: 3
posted @ 2022-11-10 23:00  呆萌老师  阅读(350)  评论(0编辑  收藏  举报