Eureka —— 第一代Spring Cloud核心组件高级应用

目录

一. Eureka介绍

(一)服务注册中⼼⼀般原理

(二)主流服务中⼼对⽐

1. Zookeeper

2. Eureka

3. Consul

4. Nacos

(三)服务注册中⼼组件 Eureka

1. Eureka 基础架构

2. Eureka 交互流程及原理

二. Eureka应⽤及⾼可⽤集群

(一)搭建单例Eureka Server服务注册中⼼

(二)搭建Eureka Server HA⾼可⽤集群

(三)微服务提供者—>注册到Eureka Server集群

(四)微服务消费者—>注册到Eureka Server集群

(五)服务消费者调⽤服务提供者(通过Eureka)

三. Eureka细节详解

(一)Eureka元数据详解

 (二)Eureka客户端详解

1. 服务注册详解(服务提供者)

2. 服务续约详解(服务提供者)

3. 获取服务列表详解(服务消费者)

(三)Eureka服务端详解

1. 服务下线

2. 失效剔除

3. ⾃我保护

四. Eureka组件使用完整代码示例


一. Eureka介绍

注意:服务注册中⼼本质上是为了解耦服务提供者和服务消费者。

对于任何⼀个微服务,原则上都应存在或者⽀持多个提供者(⽐如简历微服务部署
多个实例),这是由微服务的 分布式属性 决定的。
更进⼀步,为了⽀持弹性扩缩容特性,⼀个微服务的提供者的数量和分布往往是动
态变化的,也是⽆法预先确定的。因此,原本在单体应⽤阶段常⽤的静态 LB 机制就
不再适⽤了,需要引⼊额外的组件来管理微服务提供者的注册与发现,⽽这个组件
就是服务注册中⼼。

(一)服务注册中⼼⼀般原理

分布式微服务架构中,服务注册中⼼⽤于存储服务提供者地址信息、服务发布相关
的属性信息,消费者通过主动查询和被动通知的⽅式获取服务提供者的地址信息,
⽽不再需要通过硬编码⽅式得到提供者的地址信息。消费者只需要知道当前系统发
布了那些服务,⽽不需要知道服务具体存在于什么位置,这就是透明化路由。
1 )服务提供者启动
2 )服务提供者将相关服务信息主动注册到注册中⼼
3 )服务消费者获取服务注册信息:
pull 模式:服务消费者可以主动拉取可⽤的服务提供者清单
push 模式:服务消费者订阅服务(当服务提供者有变化时,注册中⼼也会主动推送
更新后的服务清单给消费者
4 )服务消费者直接调⽤服务提供者
另外,注册中⼼也需要完成服务提供者的健康监控,当发现服务提供者失效时需要
及时剔除;

(二)主流服务中⼼对⽐

1. Zookeeper

Zookeeper 它是⼀个分布式服务框架,是 Apache Hadoop 的⼀个⼦项⽬,它主
要是⽤来解决分布式应 ⽤中经常遇到的⼀些数据管理问题,如:统⼀命名服
务、状态同步服务、集群管理、分布式应⽤配置项的管理等。
简单来说 zookeeper 本质 = 存储 + 监听通知。
znode
Zookeeper ⽤来做服务注册中⼼,主要是因为它具有节点变更通知功能,只要
客户端监听相关服务节点,服务节点的所有变更,都能及时的通知到监听客户
端,这样作为调⽤⽅只要使⽤ Zookeeper 的客户端就能实现服务节点的订阅和
变更通知功能了,⾮常⽅便。另外, Zookeeper 可⽤性也可以,因为只要半数
以上的选举节点存活,整个集群就是可⽤的。

2. Eureka

Netflflix 开源,并被 Pivatal 集成到 SpringCloud 体系中,它是基于 RestfulAPI
⻛格开发的服务注册与发现组件。

3. Consul

Consul 是由 HashiCorp 基于 Go 语⾔开发的⽀持多数据中⼼分布式⾼可⽤的服务
发布和注册服务软件, 采⽤ Raft 算法保证服务的⼀致性,且⽀持健康检查。

4. Nacos

Nacos 是⼀个更易于构建云原⽣应⽤的动态服务发现、配置管理和服务管理平
台。简单来说 Nacos 就是 注册中⼼ + 配置中⼼的组合,帮助我们解决微服务开
发必会涉及到的服务注册 与发现,服务配置,服务管理等问题。 Nacos
Spring Cloud Alibaba 核⼼组件之⼀,负责服务注册与发现,还有配置。

P :分区容错性(⼀定的要满⾜的)
C :数据⼀致性
A :⾼可⽤
CAP 不可能同时满⾜三个,要么是 AP ,要么是 CP

(三)服务注册中⼼组件 Eureka

服务注册中⼼的⼀般原理、对⽐了主流的服务注册中⼼⽅案
⽬光聚焦 Eureka

1. Eureka 基础架构

 

2. Eureka 交互流程及原理

下图是官⽹描述的⼀个架构图

 

Eureka 包含两个组件: Eureka Server Eureka Client Eureka Client 是⼀个
Java 客户端,⽤于简化与 Eureka Server 的交互; Eureka Server 提供服务发现的
能⼒,各个微服务启动时,会通过 Eureka Client Eureka Server 进⾏注册⾃⼰
的信息(例如⽹络信息), Eureka Server 会存储该服务的信息;
1 )图中 us-east-1c us-east-1d us-east-1e 代表不同的区也就是不同的机房
2 )图中每⼀个 Eureka Server 都是⼀个集群。
3 )图中 Application Service 作为服务提供者向 Eureka Server 中注册服务,
Eureka Server 接受到注册事件会在集群和分区中进⾏数据同步, Application
Client 作为消费端(服务消费者)可以从 Eureka Server 中获取到服务注册信
息,进⾏服务调⽤。
4 )微服务启动后,会周期性地向 Eureka Server 发送⼼跳(默认周期为 30 秒)
以续约⾃⼰的信息
5 Eureka Server 在⼀定时间内没有接收到某个微服务节点的⼼跳, Eureka
Server 将会注销该微服务节点(默认 90 秒)
6 )每个 Eureka Server 同时也是 Eureka Client ,多个 Eureka Server 之间通过复
制的⽅式完成服务注册列表的同步
7 Eureka Client 会缓存 Eureka Server 中的信息。即使所有的 Eureka Server
点都宕掉,服务消费者依然可以使⽤缓存中的信息找到服务提供者

Eureka 通过⼼跳检测、健康检查和客户端缓存等机制,提⾼系统的灵活性、可
伸缩性和可⽤性。

二. Eureka应⽤及⾼可⽤集群

1 )单实例 Eureka Server—> 访问管理界⾯ —>Eureka Server 集群
2 )服务提供者(简历微服务注册到集群)
3 )服务消费者(⾃动投递微服务注册到集群 / Eureka Server 集群获取服务信息)
4 )完成调⽤

(一)搭建单例Eureka Server服务注册中⼼

pc-service-resume 8080-----
pc-service-autodeliver 8090----
pc-cloud-eureka-server 8761----
基于 Maven 构建 SpringBoot ⼯程,在 SpringBoot ⼯程之上搭建 EurekaServer 服务
pc-cloud-eureka-server-8761)
  • pc-parent中引⼊Spring Cloud 依赖
Spring Cloud 是⼀个综合的项⽬,下⾯有很多⼦项⽬,⽐如 eureka ⼦项⽬(版
本号 1.x.x
    <dependencyManagement>
        <dependencies>
            <!--spring cloud依赖管理,引入了Spring Cloud的版本-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
  • pc-cloud-eureka-server⼯程pom.xml中引⼊依赖
        <!--Eureka server依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
注意:在⽗⼯程的 pom ⽂件中⼿动引⼊ jaxb jar ,因为 Jdk9 之后默认没有加载该模
块, EurekaServer 使⽤到,所以需要⼿动导⼊,否则 EurekaServer 服务⽆法启动
 <!--eureka server 需要引入Jaxb,开始-->
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.2.11</version>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.11</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jaxb</groupId>
            <artifactId>jaxb-runtime</artifactId>
            <version>2.2.10-b140310.1920</version>
        </dependency>
        <dependency>
            <groupId>javax.activation</groupId>
            <artifactId>activation</artifactId>
            <version>1.1.1</version>
        </dependency>
        <!--引入Jaxb,结束-->
  • pc-cloud-eureka-server⼯程application.yml
#eureka server服务端口
server:
  port: 8761
spring:
  application:
    name: pc-cloud-eureka-server # 应用名称,应用名称会在Eureka中作为服务名称

    # eureka 客户端配置(和Server交互),Eureka Server 其实也是一个Client
eureka:
  instance:
    hostname: localhost # 当前eureka实例的主机名
  client:
    service-url:
      # 配置客户端所交互的Eureka Server的地址(Eureka Server集群中每一个Server其实相对于其它Server来说都是Client)
      # 集群模式下,defaultZone应该指向其它Eureka Server,如果有更多其它Server实例,逗号拼接即可
      defaultZone: http://localhost:8761/eureka(单例模式)
    register-with-eureka: false  # 集群模式下可以改成true(单例模式下当前自己就是Server,不需要注册自己)
    fetch-registry: false # 集群模式下可以改成true(获取注册中心的服务信息,单例模式下当前自己就是Server,不需要获取)
  • SpringBoot启动类,使⽤@EnableEurekaServer声明当前项⽬为EurekaServer服务
package com.pc.edu;

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

@SpringBootApplication
// 声明当前项目为Eureka服务
@EnableEurekaServer
public class PcEurekaServerApp8761 {

    public static void main(String[] args) {
        SpringApplication.run(PcEurekaServerApp8761.class,args);
    }
}
  • 执⾏启动类PcCloudEurekaServerApplicationmain函数
  • 访问http://127.0.0.1:8761,如果看到如下⻚⾯(Eureka注册中⼼后台),则表EurekaServer发布成功

 

 

(二)搭建Eureka Server HA⾼可⽤集群

在互联⽹应⽤中,服务实例很少有单个的。
即使微服务消费者会缓存服务列表,但是如果 EurekaServer 只有⼀个实例,该实例
挂掉,正好微服务消费者本地缓存列表中的服务实例也不可⽤,那么这个时候整个
系统都受影响。
在⽣产环境中,我们会配置 Eureka Server 集群实现⾼可⽤。 Eureka Server 集群之
中的节点通过点对点( P2P )通信的⽅式共享服务注册表。我们开启两台 Eureka
Server 以搭建集群。

(1 )修改本机 host 属性
由于是在个⼈计算机中进⾏测试很难模拟多主机的情况, Eureka 配置 server 集群时
需要执⾏ host 地址。 所以需要修改个⼈电脑中 host 地址
127.0.0.1 PcCloudEurekaServerA
127.0.0.1 PcCloudEurekaServerB
(2 )修改 pc-cloud-eureka-server ⼯程中的 yml 配置⽂件
#eureka server服务端口
server:
  port: 8761
spring:
  application:
    name: pc-cloud-eureka-server # 应用名称,应用名称会在Eureka中作为服务名称

    # eureka 客户端配置(和Server交互),Eureka Server 其实也是一个Client
eureka:
  instance:
    hostname: PcCloudEurekaServerA  # 当前eureka实例的主机名
  client:
    service-url:
      # 配置客户端所交互的Eureka Server的地址(Eureka Server集群中每一个Server其实相对于其它Server来说都是Client)
      # 集群模式下,defaultZone应该指向其它Eureka Server,如果有更多其它Server实例,逗号拼接即可
      defaultZone: http://PcCloudEurekaServerB:8762/eureka # http://localhost:8761/eureka(单例模式)
    register-with-eureka: true  # 集群模式下可以改成true(单例模式下当前自己就是Server,不需要注册自己)
    fetch-registry: true # 集群模式下可以改成true(获取注册中心的服务信息,单例模式下当前自己就是Server,不需要获取)

(三)微服务提供者—>注册到Eureka Server集群

注册简历微服务 (简历服务部署两个实例,分别占⽤ 8080 8081 端⼝)
  • ⽗⼯程中引⼊spring-cloud-commons依赖
        <!--spring cloud commons模块引入-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>
  • 注册简历微服务 pom⽂件引⼊坐标,添加eureka client的相关坐标
        <!--eureka client 客户端依赖引入-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  •  配置application.yml⽂件

application.yml 中添加Eureka Server⾼可⽤集群的地址及相关配置

server:
  port: 8080
spring:
  application:
    name: pc-service-resume
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.200.128:3306/lagou?useUnicode=true&characterEncoding=utf8
    username: root
    password: PcPc@123
  jpa:
    database: MySQL
    show-sql: true
    hibernate:
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl  #避免将驼峰命名转换为下划线命名
#注册到Eureka服务中心
eureka:
  client:
    service-url:
      # 注册到集群,就把多个Eurekaserver地址使用逗号连接起来即可;注册到单实例(非集群模式),那就写一个就ok
      defaultZone: http://PcCloudEurekaServerA:8761/eureka,http://PcCloudEurekaServerB:8762/eureka
  instance:
    prefer-ip-address: true  #服务实例中显示ip,而不是显示主机名(兼容老的eureka版本)
    # 实例名称: 192.168.1.103:pc-service-resume:8080,我们可以自定义它
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
经验:⾃定义实例显示格式,加上版本号,便于多版本管理

  • 启动类添加注解

 注意:

1 )从 Spring Cloud Edgware 版本开始, @EnableDiscoveryClient
@EnableEurekaClient 可省略。只需加 上相关依赖,并进⾏相应配置,即可将
微服务注册到服务发现组件上。
2 @EnableDiscoveryClient @EnableEurekaClient ⼆者的功能是⼀样的。但
是如果选⽤的是 eureka 服务器,那么就推荐 @EnableEurekaClient ,如果是其
他的注册中⼼,那么推荐使⽤ @EnableDiscoveryClient ,考虑到通⽤性,后期
我们可以使⽤ @EnableDiscoveryClient
  • 启动类执⾏,在Eureka Server后台界⾯可以看到注册的服务实例

(四)微服务消费者—>注册到Eureka Server集群

此处⾃动注册微服务是消费者
  • 微服务消费者 pom⽂件引⼊坐标,添加eureka client的相关坐标
        <!--eureka client 客户端依赖引入-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  • 配置application.yml⽂件
server:
  port: 8090
#注册到Eureka服务中心
eureka:
  client:
    service-url:
      # 注册到集群,就把多个Eurekaserver地址使用逗号连接起来即可;注册到单实例(非集群模式),那就写一个就ok
      defaultZone: http://PcCloudEurekaServerA:8761/eureka,http://PcCloudEurekaServerB:8762/eureka
  instance:
    prefer-ip-address: true  #服务实例中显示ip,而不是显示主机名(兼容老的eureka版本)
    # 实例名称: 192.168.1.103:lagou-service-resume:8080,我们可以自定义它
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
spring:
  application:
    name: pc-service-autodeliver
  • 在启动类添加注解@EnableDiscoveryClient,开启服务发现
package com.pc.edu;



import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableDiscoveryClient
public class AutodeliverApplication8090 {

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


    // 使用RestTemplate模板对象进行远程调用
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

}

(五)服务消费者调⽤服务提供者(通过Eureka

三. Eureka细节详解

(一)Eureka元数据详解

Eureka 的元数据有两种:标准元数据和⾃定义元数据。
标准元数据: 主机名、 IP 地址、端⼝号等信息,这些信息都会被发布在服务注册表
中,⽤于服务之间的调⽤。
⾃定义元数据: 可以使⽤ eureka.instance.metadata-map 配置,符合 KEY/VALUE
存储格式。这 些元数据可以在远程客户端中访问。
类似于
instance :
     prefer-ip-address : true
     metadata-map :
         # ⾃定义元数据 (kv ⾃定义 )
         cluster : cl1
         region : rn1

我们可以在程序中可以使⽤DiscoveryClient 获取指定微服务的所有元数据信息

import com.pc.edu.AutodeliverApplication8090;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@SpringBootTest(classes = {AutodeliverApplication8090.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class AutodeliverApplication8090Test {


    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;


    @Test
    public void testInstanceMetadata() {
        List<ServiceInstance> instances = discoveryClient.getInstances("pc-service-resume-8080");
        for (int i = 0; i < instances.size(); i++) {
            ServiceInstance serviceInstance =  instances.get(i);
            System.out.println(serviceInstance);
        }
    }


}
元数据查看如下

 

 (二)Eureka客户端详解

服务提供者(也是 Eureka 客户端)要向 EurekaServer 注册服务,并完成服务续约等⼯作

1. 服务注册详解(服务提供者)

1 )当我们导⼊了 eureka-client 依赖坐标,配置 Eureka 服务注册中⼼地址
2 )服务在启动时会向注册中⼼发起注册请求,携带服务元数据信息
3 Eureka 注册中⼼会把服务的信息保存在 Map 中。

2. 服务续约详解(服务提供者)

服务每隔 30 秒会向注册中⼼续约 ( ⼼跳 ) ⼀次(也称为报活),如果没有续约,租约在
90 秒后到期,然后服务会被失效。每隔 30 秒的续约操作我们称之为⼼跳检测
往往不需要我们调整这两个配置

3. 获取服务列表详解(服务消费者)

每隔 30 秒服务会从注册中⼼中拉取⼀份服务列表,这个时间可以通过配置修改。往
往不需要我们调整

1 )服务消费者启动时,从 EurekaServer 服务列表获取只读备份,缓存到本地
2 )每隔 30 秒,会重新获取并更新数据
3 )每隔 30 秒的时间可以通过配置 eureka.client.registry-fetch-interval-seconds

(三)Eureka服务端详解

1. 服务下线

1 )当服务正常关闭操作时,会发送服务下线的 REST 请求给 EurekaServer
2 )服务中⼼接受到请求后,将该服务置为下线状态

2. 失效剔除

Eureka Server 会定时(间隔值是 eureka.server.eviction-interval-timer-in-ms ,默
60s )进⾏检查,如果发现实例在在⼀定时间(此值由客户端设置的
eureka.instance.lease-expiration-duration-in-seconds 定义,默认值为 90s )内没
有收到⼼跳,则会注销此实例。

3. ⾃我保护

服务提供者 —> 注册中⼼
定期的续约(服务提供者和注册中⼼通信),假如服务提供者和注册中⼼之间的⽹
络有点问题,不代表服务提供者不可⽤,不代表服务消费者⽆法访问服务提供者
如果在 15 分钟内超过 85% 的客户端节点都没有正常的⼼跳,那么 Eureka 就认为客户
端与注册中⼼出现了⽹络故障, Eureka Server ⾃动进⼊⾃我保护机制。
为什么会有⾃我保护机制?
默认情况下,如果 Eureka Server 在⼀定时间内(默认 90 秒)没有接收到某个微服务
实例的⼼跳, Eureka Server 将会移除该实例。但是当⽹络分区故障发⽣时,微服务
Eureka Server 之间⽆法正常通信,⽽微服务本身是正常运⾏的,此时不应该移除
这个微服务,所以引⼊了⾃我保护机制。
服务中⼼⻚⾯会显示如下提示信息
当处于⾃我保护模式时
1 )不会剔除任何服务实例(可能是服务提供者和 EurekaServer 之间⽹络问题),保
证了⼤多数服务依然可⽤
2 Eureka Server 仍然能够接受新服务的注册和查询请求,但是不会被同步到其它
节点上,保证当前节点依然可⽤,当⽹络稳定时,当前 Eureka Server 新的注册信息
会被同步到其它节点中。
3 )在 Eureka Server ⼯程中通过 eureka.server.enable-self-preservation 配置可⽤
关停⾃我保护,默认值是打开

建议⽣产环境打开⾃我保护机制

四. Eureka组件使用完整代码示例

Eureka AND Ribbon 应用完整示例代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值