天天看点

SpringCloud -- Eureka一、Eureka简介二、Eureka搭建

一、Eureka简介

Eureka是Netflix开发的服务发现框架,其是基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能。

1、Eureka组件

Eureka 包含: Eureka Server 和 Eureka Client (Producer生产提供者 和Consumer生产消费者)

1.1 Eureka Server

Eureka Server 提供注册服务,微服务内的相关应用服务按注册要求配置后,启动相关应用服务节点后,会在Eureka Server中进行注册,这样Eureka Server内的服务注册表将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的展现。

Eureka Server本身也是一个服务,默认情况下会自动注册到Eureka注册中心。

如果搭建单机版的Eureka Server注册中心,则需要配置取消Eureka Server的自动注册逻辑。

Eureka Server通过Register、Get、Renew 等接口提供服务的注册、发现和心跳检测等服务。

服务注册(Register)

服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息:元数据,比如 IP 地址、端口、运行状况指示符 URL、主页等,Eureka Server 内部有二层缓存机制来维护整个注册表。

1.2 Eureka Client

Eureka Client 是Java客户端,用于与Eureka Server的交互,客户端具备内置的、使用轮询(round-robin)负载算法的负载均衡器。

当应用服务启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个(默认90秒/30秒)心跳周期内没有接收到某应用服务节点的心跳,Eureka Server将会从服务注册表内将此应用服务节点移除。

Eureka Client分为两个角色,分别是:Service Provider 和 Service Consumer。

Service Provider 和 Service Consumer 并不是绝对的,因为Provider在提供服务的同时,也可以消费其他Provider提供的服务;Consumer在消费服务的同时,也可以提供对外服务。

Register: 服务注册

服务的提供者,将自身注册到注册中心,服务提供者也是 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口、运行状况指示符 URL、主页等。

Renew: 服务续约

Eureka Client 会每隔 30 秒发送心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。

默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,Server 端会将实例从其注册表内删除,此时间可配置,一般情况不建议更改。

服务续约配置:

# 服务续约任务的调用间隔时间,默认为30秒
eureka.instance.lease-renewal-interval-in-seconds=30
# 服务失效的时间,默认为90秒。
eureka.instance.lease-expiration-duration-in-seconds=90
           

Cancel: 服务下线

Eureka Client 在服务程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表内删除。

服务下线需请求如下接口:

DiscoveryManager.getInstance().shutdownComponent();
           

GetRegisty: 获取注册列表信息

Eureka Client 从Eureka Server 获取注册表信息,并将其缓存在本地。Eureka Client会使用该注册表信息查找消费其他服务,从而进行远程调用。该注册列表信息定期更新频率1次/30秒。

注意,获取的注册表信息可能与实际的注册表信息不符。

若因某种原因导致注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息。 Eureka Server 缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka Client 和 Eureka Server 可以使用 JSON/XML 格式进行通讯。在默认情况下 Eureka Client 使用压缩 JSON 格式来获取注册列表的信息。

Cancel: 服务下线

Replicate:同步状态

当 Provider 关闭时会向Eureka发送消息,把自己从服务列表中删除。防止 Consumer 调用到不存在的服务。

Make Remote Call:远程调用

当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡,完成服务的远程调用。

1.3 自我保护机制

服务保护模式(自我保护模式):一般情况下,微服务在Eureka上注册后,会每30秒发送心跳包,Eureka通过心跳来判断服务时候健康,同时会定期删除超过90秒没有发送心跳服务。

导致Eureka Server接收不到心跳包的可能:

A:微服务自身的原因;

B:微服务与Eureka之间的网络故障;

通常微服务自身的故障只会导致个别服务出现故障,一般不会出现大面积故障,而网络故障通常会导致Eureka Server在短时间内无法收到大批心跳。

考虑到网络故障情况,Eureka设置了1个阀值,当判断挂掉的服务的数量超过阀值时,Eureka Server认为很大程度是因出现网络故障,将不再删除心跳过期的服务。

这个阀值是多少呢?Eureka Server在运行期间,会统计心跳失败的比例在15分钟内是否低于85%,如果低于85%,Eureka Server则任务是网络故障,不会删除心跳过期服务。

这种服务保护算法叫做Eureka Server的服务保护模式。

这种不删除的,90秒没有心跳的服务,称为无效服务,但是还是保存在服务列表中。如果Consumer到注册中心发现服务,则Eureka Server会将所有好的数据(有效服务数据)和坏的数据(无效服务数据)都返回给Consumer。

通过 Eureka Server 配置参数,开启或者关闭保护机制,生产环境建议打开:

eureka.server.enable-self-preservation=true
           

1.4 Eurka 工作流程

(1)、Eureka Server 启动成功,等待服务端注册。若启动过程中配置过Cluster,Cluster之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息;

(2)、Eureka Client 启动时,根据配置的 Eureka Server 地址去注册中心注册服务;

(3)、Eureka Client 会每 30秒 向 Eureka Server 发送一次心跳请求,证明客户端服务正常;

(4)、当 Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例;

(5)、单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有发送心跳的客户端;

(6)、当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式;

(7)、Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地;

(8)、服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存;

(9)、Eureka Client 获取到目标服务器信息,发起服务调用;

(10)、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除。

二、Eureka搭建

2、Eureka Server 搭建

2.1 Eureka Server单节点

配置:build.gradle

plugins {
    id 'org.springframework.boot' version '2.4.1'
    id 'io.spring.dependency-management' version '1.0.10.RELEASE'
    id 'java'
}

group = 'com.boy'
version = '1.0.0'
sourceCompatibility = '1.8'

repositories {
    mavenLocal()
    mavenCentral()
    maven { url 'https://maven.aliyun.com/repository/public/' }
    maven { url 'https://maven.aliyun.com/repository/spring/'}
    maven { url "https://repo1.maven.org/maven2/" }
    maven { url 'https://repo.spring.io/milestone' }
    maven { url "https://mvnrepository.com/repos/central/" }
    maven { url "http://jcenter.bintray.com" }
    maven { url "http://mvn.gt.igexin.com/nexus/content/repositories/releases" }
    maven { url "https://plugins.gradle.org/m2/" }
    maven { url "https://repo.spring.io/plugins-release/" }
    maven { url "https://repo.spring.io/milestone" }
    maven { url "https://oss.sonatype.org/content/repositories/releases/" }
    maven { url "https://maven.repository.redhat.com/ga/" }
    maven { url "https://repository.apache.org/content/repositories/releases/" }

    jcenter()
}

ext {
    set('springCloudVersion', "2020.0.0")
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-server'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

test {
    useJUnitPlatform()
}
           

配置application.yml: 

#单节点
server:
  port: 7900
#应用名称及验证账号
spring:
  application:
    name: EUREKA-SERVER
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    #关闭自我保护
    enable-self-preservation: false
    #清理间隔时间
    eviction-interval-timer-in-ms: 5000
logging:
  level:
    root: info
           

启动类: 

package com.boy.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

2.2 Eureka Server两节点搭建

配置application.yml: 

# \u4E24\u8282\u70B9\u642D\u5EFA
# \u5E94\u7528\u540D\u79F0
spring:
  application:
    name: EUREKA-SERVER
logging:
  level:
    root: debug

---
spring:
  profiles: 7901
server:
  port: 7901
eureka:
  instance:
    hostname: eureka.server.one
  client:
    #\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
    service-url:
      defaultZone: http://eureka.server.two:7902/eureka/,http://eureka.server.one:7901/eureka/
---
spring:
  profiles: 7902
server:
  port: 7902
eureka:
  instance:
    hostname: eureka.server.two
  client:
    #\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
    service-url:
      defaultZone: http://eureka.server.one:7901/eureka/,http://eureka.server.one:7902/eureka/
           

配置windows hosts文件:

127.0.0.1    eureka.server.one
127.0.0.1    eureka.server.two
127.0.0.1    eureka.server.third
           

启动类:

package com.boy.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

idea启动配置:

SpringCloud -- Eureka一、Eureka简介二、Eureka搭建

2.3 Eureka Server三节点搭建

# \u4E24\u8282\u70B9\u642D\u5EFA
# \u5E94\u7528\u540D\u79F0
spring:
  application:
    name: EUREKA-SERVER
logging:
  level:
    root: debug
server:
  servlet:
    context-path: /eureka/
---
spring:
  profiles: 7901
server:
  port: 7901
eureka:
  instance:
    hostname: eureka.server.one
  client:
    #\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
    service-url:
      defaultZone: http://eureka.server.two:7902/eureka/,http://eureka.server.third:7903/eureka/,http://eureka.server.one:7901/eureka/
---
spring:
  profiles: 7902
server:
  port: 7902
eureka:
  instance:
    hostname: eureka.server.two
  client:
    #\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
    service-url:
      defaultZone: http://eureka.server.third:7903/eureka/,http://eureka.server.one:7901/eureka/,http://eureka.server.two:7902/eureka/
---
spring:
  profiles: 7903
server:
  port: 7903
eureka:
  instance:
    hostname: eureka.server.third
  client:
    #\u8BBE\u7F6E\u670D\u52A1\u6CE8\u518C\u4E2D\u5FC3\u7684URL
    service-url:
      defaultZone: http://eureka.server.one:7901/eureka/,http://eureka.server.two:7902/eureka/,http://eureka.server.third:7903/eureka/
           

 idea启动配置:

SpringCloud -- Eureka一、Eureka简介二、Eureka搭建