目录

注册中心

Eureka 介绍

Eureka Server

服务注册

提供注册表

同步状态

Eureka Client:注册中心客户端

Register: 服务注册

Renew: 服务续约

Eviction 服务剔除

Cancel: 服务下线

GetRegisty: 获取注册列表信息

Remote Call: 远程调用

自我保护机制

Eureka 集群原理

Eurka 工作流程

Eureka 使用

单机版

集群版



注册中心

系统会根据业务被拆分成了很多的微服务,微服务的信息如何管理?
Spring Cloud中提供服务注册中心来管理微服务信息。
注册中心模型

在简介中我大致说明了一下什么是注册中心,理解的同学直接跳过,不理解的同学可以再看一下另一个例子。大家应该都知道世纪佳缘,百合网等各种相亲网站。那么这些网站要做的事情是什么呢?大致过程不过是,用户把自己的信息注册进去,把对另一半的要求填进去,然后,系统帮你匹配合适的对象。这里每个用户就是一个微服务,用户在网站注册自己信息,就是微服务向注册中心注册,对对方的要求,就是一个微服务想要找的另外一个微服务的信息。

为什么要用注册中心?
  • 微服务数量众多,要进行远程调用就需要知道服务端的ip地址和端口,假如我们把需要远程调用的微服务地址写死在代码里,哪怕是写在配置文件里,如果这个微服务挂掉了怎么办?如果这个微服务部署到新的地址怎么办?难道我要停掉我的微服务改代码吗?这不是在开玩笑吗?注册中心帮助我们管理这些服务的ip和端口,我只需要知道我要调用的微服务名字就行了,你的地址我从注册中心去拿,你爱部署到哪我都不关心。
  • 微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。

Eureka 介绍

  • Spring Cloud Eureka 是对Netflflix公司的Eureka的二次封装,它实现了服务治理的功能,Spring Cloud Eureka 提供 Eureka Server 服务端与 Eureka Client 客户端 ,服务端即是Eureka服务注册中心,客户端完成微服务向Eureka服务的注册与发现。
  • 客户端同时也具备一个内置的使用轮询负载算法的负载均衡器。在微服务启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

下图显示了 Eureka Server 与 Eureka Client 的关系

  • Eureka Server 是服务端,负责管理各个微服务注册和发现。
  • 在微服务上添加 Eureka Client 代码,就会访问到 Eureka Server 将此微服务注册在Eureka Server中,从而使服务消费方能够找到。
  • 微服务(服务消费者)需要调用另一个微服务(服务提供者)时,从 Eureka Server 中获取服务调用地址,进行远程调用。

接下来我们看一看详情。参考:Eureka工作原理

Eureka Server

注册中心服务端主要对外提供了三个功能:

服务注册

服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息,Eureka Server 内部有二层缓存机制来维护整个注册表。

提供注册表

服务消费者在调用服务时,如果 Eureka Client 没有缓存注册表的话,会从 Eureka Server 获取最新的注册表

同步状态

Eureka Client 通过注册、心跳机制和 Eureka Server 同步当前客户端的状态。

Eureka Client:注册中心客户端

Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互。Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。

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

Eviction 服务剔除

当 Eureka Client 和 Eureka Server 不再有心跳时,Eureka Server 会将该服务实例从服务注册列表中删除,即服务剔除。

Cancel: 服务下线

Eureka Client 在程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:

DiscoveryManager.getInstance().shutdownComponent();

GetRegisty: 获取注册列表信息

Eureka Client 从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与 Eureka Client 的缓存信息不同,Eureka Client 自动处理。

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

获取服务是服务消费者的基础,所以必有两个重要参数需要注意:

# 启用服务消费者从注册中心拉取服务列表的功能
eureka.client.fetch-registry=true# 设置服务消费者从注册中心拉取服务列表的间隔
eureka.client.registry-fetch-interval-seconds=30

Remote Call: 远程调用

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

自我保护机制

默认情况下,如果 Eureka Server 在一定的 90s 内没有接收到某个微服务实例的心跳,会注销该实例。但是在微服务架构下服务之间通常都是跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,网络分区故障,导致此实例被注销。

固定时间内大量实例被注销,可能会严重威胁整个微服务架构的可用性。为了解决这个问题,Eureka 开发了自我保护机制,那么什么是自我保护机制呢?

Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 即会进入自我保护机制。

Eureka Server 进入自我保护机制,会出现以下几种情况:
(1 Eureka 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
(2 Eureka 仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
(3 当网络稳定时,当前实例新的注册信息会被同步到其它节点中

Eureka 自我保护机制是为了防止误杀服务而提供的一个机制。当个别客户端出现心跳失联时,则认为是客户端的问题,剔除掉客户端;当 Eureka 捕获到大量的心跳失败时,则认为可能是网络问题,进入自我保护机制;当客户端心跳恢复时,Eureka 会自动退出自我保护机制。

如果在保护期内刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,即会调用失败。对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。

Eureka 自我保护很明显保护的是服务端,因为微服务不会因为被删除了注册表中的信息而改变自己状态,就像你不会因为世纪佳缘删了你的消息,而对你有什么影响,顶多就是匹配不到你而已。它的目的是为了保护服务端自己,假如是因为网络问题,服务端把注册表中信息都删掉了,这个注册中心还有什么用?空壳一个。举个不恰当的例子,A在世纪佳缘注册了信息,A挂掉了,删除A的信息属于正常操作,你不能因为打电话没有联系上A就把A删了,过一会说不定就打通了呢。因为这把注册的人都删了,我还办什么婚姻介绍所是不是。

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

eureka.server.enable-self-preservation=true

Eureka 集群原理

我们假设有三台 Eureka Server 组成的集群,第一台 Eureka Server 在北京机房,另外两台 Eureka Server 在深圳和西安机房。这样三台 Eureka Server 就组建成了一个跨区域的高可用集群,只要三个地方的任意一个机房不出现问题,都不会影响整个架构的稳定性。

从图中可以看出 Eureka Server 集群相互之间通过 Replicate 来同步数据,相互之间不区分主节点和从节点,所有的节点都是平等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。

如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点。当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会进行节点间复制,将请求复制到其它 Eureka Server 当前所知的所有节点中。

另外 Eureka Server 的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。所以,如果存在多个节点,只需要将节点之间两两连接起来形成通路,那么其它注册中心都可以共享信息。每个 Eureka Server 同时也是 Eureka Client,多个 Eureka Server 之间通过 P2P 的方式完成服务注册表的同步。

Eureka Server 集群之间的状态是采用异步方式同步的,所以不保证节点间的状态一定是一致的,不过基本能保证最终状态是一致的。

Eureka 分区
Eureka 提供了 Region 和 Zone 两个概念来进行分区,这两个概念均来自于亚马逊的 AWS:
region:可以理解为地理上的不同区域,比如亚洲地区,中国区或者深圳等等。没有具体大小的限制。根据项目具体的情况,可以自行合理划分 region。
zone:可以简单理解为 region 内的具体机房,比如说 region 划分为深圳,然后深圳有两个机房,就可以在此 region 之下划分出 zone1、zone2 两个 zone。

上图中的 us-east-1c、us-east-1d、us-east-1e 就代表了不同的 Zone。Zone 内的 Eureka Client 优先和 Zone 内的 Eureka Server 进行心跳同步,同样调用端优先在 Zone 内的 Eureka Server 获取服务列表,当 Zone 内的 Eureka Server 挂掉之后,才会从别的 Zone 中获取信息。

Eureka 保证 AP

Eureka Server 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka Client 在向某个 Eureka 注册时,如果发现连接失败,则会自动切换至其它节点。只要有一台 Eureka Server 还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。

Eureka 工作流程

了解完 Eureka 核心概念,自我保护机制,以及集群内的工作原理后,我们来整体梳理一下 Eureka 的工作流程:

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

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

3、Eureka Client 会每 30s 向 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 将实例从注册表中删除

这就是Eurka基本工作流程。

Eureka 使用

原理说到这里就差不多了,再深入,就需要之后的使用中慢慢体会了,现在来吧,练一练……

单机版

继续上一篇的项目。先来一个单机版的Eureka

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>parent</artifactId><groupId>com.haogenmin.springcloud</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>eureka_01</artifactId><dependencies><!-- 导入Eureka-server 服务端依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies></project>

配置文件

server:port: 6001 # 服务端口eureka:instance:hostname: eureka6001.com # eureka服务端的实例名称client:registerWithEureka: false # 服务注册,false表示不将自已注册到Eureka服务中fetchRegistry: false # 服务发现,false表示自己不从Eureka服务中获取注册信息serviceUrl:    # Eureka客户端与Eureka服务端的交互地址,集群版配置对方的地址,单机版配置自己(如果不配置则默认本机8761端口)defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/server:enable-self-preservation: false # 禁用自我保护机制

启动类

package com.haogenmin.eureka1;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;/*** @author :HaoGenmin* @Title :Eureka_01_Application* @date :Created in 2020/6/24 16:07* @description:*/
@SpringBootApplication
@EnableEurekaServer
public class Eureka_01_Application {public static void main(String[] args) {SpringApplication.run(Eureka_01_Application.class,args);}
}

注意:

  • 启动类上面要有@EnableEurekaServer注解,这个注解表示这是一个服务注册中心。
  • eureka6001.com 这玩意其实就是localhost,是自己电脑上配的,你要懒得配可以自己改成127.0.0.1。

跑起来:

现在,我们把之前的服务提供者注册进去。

在provider的pom文件里面加入:

        <!-- 导入Eureka客户端的依赖,将 微服务提供者 注册进 Eureka --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>

改变其yml配置文件加入以下内容:

eureka:client:registerWithEureka: true # 服务注册开关fetchRegistry: true # 服务发现开关serviceUrl: # 注册到哪一个Eureka Server服务注册中心,多个中间用逗号分隔defaultZone: http://localhost:6001/eurekainstance:instanceId: ${spring.application.name}:${server.port} # 等价于microservice-product:8001prefer-ip-address: true #访问路径就会显示成IP地址

修改主启动类,加上@EnableEurekaClient表示这是一个Eureka客户端。

@SpringBootApplication
@EnableEurekaClient
public class Provider_01_Application {public static void main(String[] args) {SpringApplication.run(Provider_01_Application.class,args);}
}

好的,启动

可以发现注册中心已经有了注册信息,我们把鼠标放在绿色的连接上面发下左下角显示的ip和端口,其实就是我们在配置文件里面配置的这个玩意。

  instance:instanceId: ${spring.application.name}:${server.port} # 等价于microservice-product:8001prefer-ip-address: true #访问路径就会显示成IP地址

注册的微服务的名字就是下面这个玩意,以后我们想要访问这个微服务,就是通过他的这个名字来访问了。有朋友要问了,这名字可以重复吗?答案是,可以,而且微服务扩展的时候还必须得重复,下一篇讨论负载均衡的时候再讨论。

集群版

除配置文件外,其余跟前一个Eureka一样。

配置文件:

server:port: 6002 # 服务端口eureka:instance:hostname: eureka6002.com # eureka服务端的实例名称client:registerWithEureka: false # 服务注册,false表示不将自已注册到Eureka服务中fetchRegistry: false # 服务发现,false表示自己不从Eureka服务中获取注册信息serviceUrl:    # Eureka客户端与Eureka服务端的交互地址,集群版配置对方的地址,单机版配置自己(如果不配置则默认本机8761端口)defaultZone: http://eureka6001.com:6001/eureka/server:enable-self-preservation: false # 禁用自我保护机制

然后前一个eureka的配置文件改一下:

server:port: 6001 # 服务端口eureka:instance:hostname: eureka6001.com # eureka服务端的实例名称client:registerWithEureka: false # 服务注册,false表示不将自已注册到Eureka服务中fetchRegistry: false # 服务发现,false表示自己不从Eureka服务中获取注册信息serviceUrl:    # Eureka客户端与Eureka服务端的交互地址,集群版配置对方的地址,单机版配置自己(如果不配置则默认本机8761端口)defaultZone: http://eureka6002.com:6002/eureka/server:enable-self-preservation: false # 禁用自我保护机制

然后,把需要注册到注册中心的应用添加新的eureka地址:

测试一下:

先开启两个eureka服务,再开启需要注册的应用。

访问之后会发现,两个eureka服务都有对方的信息了,并且都有应用的注册信息。

这里集群就ok了。那么我们搭建注册中心最主要的目的是为了通过应用名获取应用服务以及实现微服务的负载均衡。那么下一篇讨论如何使用这种特性。

Spring Cloud学习笔记(三)Eureka 服务的注册与发现相关推荐

  1. Spring Cloud 学习笔记(三) 之服务治理模块Spring Cloud 服务发现与消费

    2019独角兽企业重金招聘Python工程师标准>>> 一.前言 前面的文章我们已经讲了如何搭建服务注册中心,如何搭建客户端去注册.接下来我们讲一下服务的发现与消费 二.服务注册 1 ...

  2. Spring Cloud 学习笔记(一) 之服务治理模块Spring Cloud Eureka 搭建注册中心

    2019独角兽企业重金招聘Python工程师标准>>> 关于springboot的学习请参考前面的文章 接下来我们会开启一系列关于springcloud的学习文章. 一.概念 首先我 ...

  3. Spring Cloud 学习笔记一 微服务架构

    文章目录 前言 一.微服务 二.微服务的特点 1.小型化 2.自治化 3. 扁平化 4. 轻量级设计 5. 渐进式设计 微服务架构和整体式架构的区别 微服务架构和SOA的比较 区别一:微服务通信的轻量 ...

  4. Spring Cloud 学习笔记(2 / 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(3 / 3) - - - 56_Hystrix之全局服务降级DefaultProperties 57_Hystri ...

  5. Spring Cloud 学习笔记(2 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(3 / 3) - - - 56_Hystrix之全局服务降级DefaultProperties 57_Hystri ...

  6. Spring Cloud 学习笔记(1 / 3)

    Spring Cloud 学习笔记(2 / 3) Spring Cloud 学习笔记(3 / 3) - - - 01_前言闲聊和课程说明 02_零基础微服务架构理论入门 03_第二季Boot和Clou ...

  7. Spring Cloud学习笔记

    Spring Cloud学习笔记 相关代码地址:https://github.com/gongxings/spring-cloud-study.git 一.工程环境搭建 spring cloud版本: ...

  8. Spring Cloud 学习笔记(3 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(2 / 3) - - - 108_Nacos之Linux版本安装 109_Nacos集群配置(上) 110_Nac ...

  9. Spring Cloud 学习笔记(3 / 3)

    Spring Cloud 学习笔记(1 / 3) Spring Cloud 学习笔记(2 / 3) - - - 108_Nacos之Linux版本安装 109_Nacos集群配置(上) 110_Nac ...

最新文章

  1. 为什么倒排索引不采用zlib这样的字典压缩算法——因为没法直接使用啊
  2. Oracle-OLAP和OLTP解读
  3. c语言期末作业自己设计个小程序,帮看一个小程序吧,c语言期末考…求求各位大神了...
  4. [css] 如果给一个元素设置background-color,它的颜色会填充哪些区域呢?
  5. WINCE驱动程序快速入门
  6. python 判断子序列_Leetcode练习(Python):第392题:判断子序列:给定字符串 s 和 t ,判断 s 是否为 t 的子序列。...
  7. php调用含有命名空间的类
  8. ubuntu中一些软件的命令安装及设置
  9. Windows操作系统 | Visual C++库可不能乱删
  10. 尝试Android的毛玻璃(Blur)效果
  11. python xlrd pandas_Python:Pandas pd.read_excel提供ImportError:为Excel supp安装xlrd = 0.9.0
  12. Anton and Chess
  13. 网易云音乐APP(基于APICloud平台)
  14. Echarts 柱状图横向展示和竖向展示
  15. pow函数以及math.h的一些坑
  16. 利用SUS实现自动补丁管理
  17. 重新定义股票交易中的试错和复盘
  18. python123怎么注销账号_怎么才能注销账号?
  19. Autosar E2E功能安全算法实现
  20. CSS入门基础----行内元素、块级元素和行内块元素的特点和转换

热门文章

  1. 【Web前端HTML5CSS3】03-字符实体与语义标签
  2. 20221116使用WPS将全大写的字幕转为小写的正常字幕
  3. 简单三步教你学会用Vegas做鬼畜!
  4. linux终端的 是什么意思,请问我的终端显示的是什么意思
  5. 程序猿被提bug之后的反应
  6. python getchar函数_C++:getchar()函数的用法,Cgetchar
  7. pqc的中文全称_QC中文全称
  8. mat1 and mat2 shapes cannot be multiplied
  9. 用GD32替换正点原子STM32F103ZET6
  10. webpack从0到1的配置(二)