SpringCloud系列之一---搭建高可用的Eureka注册中心

news/2024/9/20 23:23:02/
前言

本篇文章主要介绍的是SpringCloud相关知识、微服务架构以及搭建服务注册与发现的服务模块(Eureka)以及Eureka集群。

GitHub源码链接位于文章底部。

什么是SpringCloud

Spring Cloud 是一系列框架的有序集合。 它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发, 如服务发现注册、配置中心、消息总线、负载均衡、熔断器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署。Spring 并没有复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过 SpringBoot 风格进行再封装屏蔽掉了复杂的配置和实现原理,最终开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

SpringCloud 与 SpringBoot 的关系

Spring Boot是Spring的一套快速配置脚手架,可以基于Spring Boot快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的云应用开发工具;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架;Spring Boot 使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,可以不基于Spring Boot吗?不可以。
Spring Boot可以离开Spring Cloud独立使用开发项目, 但是Spring Cloud离不开Spring Boot,属于依赖的关系。

SpringCloud 主要组件
用途组件
服务发现Netflix Eureka
服务调用Netflix Feign
熔断器Netflix Hystrix
服务网关Netflix Zuul
分布式配置Spring Cloud Config
消息总线Spring Cloud Bus
SpringCloud 与 Dubbo 对比

dubbo由于是二进制的传输,占用带宽会更少。
springCloud是http协议传输,带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大。
dubbo的开发难度较大,原因是dubbo的jar包依赖问题很多大型工程无法解决。
Dubbo只是实现了服务治理,而Spring Cloud下面有很多个子项目分别覆盖了微服务架构下的方方面面,服务治理只是其中的一个方面,一定程度来说,Dubbo 只是 Spring CloudNetflix 中的一个子集。

DubboSpringCloud
服务注册中心ZookeeperSpring Cloud Netflix Eureka
服务调用方式RPCREST API
服务网关Spring Cloud Netflix Zuul /Spring Cloud GateWay
熔断器不完善Spring Cloud Netflix Hystrix
分布式配置Spring Cloud Config
服务跟踪Spring Cloud Sleuth
消息总线Spring Cloud Bus
数据流Spring Cloud Stream
批量任务Spring Cloud Task
..................
SpringCloud 的版本

SpringCloud 由于是一系列框架组合,为了避免与包含的自框架版本产生混淆,采用伦敦地铁站的名称作为版本名,形式为版本名+里程碑号。M9为第 9 个里程碑版本。以下是SpringBoot与Spring Cloud版本的对照表。

Spring BootSpring Cloud
1.2.xAngel 版本
1.3.xBrixton 版本
1.4.xCamden 版本
1.5.xDalston 版本、 Edgware 版本
2.0.xFinchley 版本
服务发现组件 Eureka

Eureka是Netflix 开发的服务发现框架,SpringCloud将它集成在自己的子项目spring-cloud-netflix中,实现SpringCloud的服务发现功能。Eureka包含两个组件:Eureka Server和Eureka Client。

Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。

自我保护机制

Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就别一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出该服务,这就是Eureka的自我保护机制。
产生原因:在开发测试时,需要频繁地重启微服务实例,但是我们很少会把eureka server一起重启(因为在开发过程中不会修改eureka注册中心),当一分钟内收到的心跳数大量减少时,会触发该保护机制。可以在eureka管理界面看到Renews threshold和Renews(last min),当后者(最后一分钟收到的心跳数)小于前者(心跳阈值)的时候,触发保护机制,会出现红色的警告:

EMERGENCY!EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT.RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEGING EXPIRED JUST TO BE SAFE.

从警告中可以看到,eureka认为虽然收不到实例的心跳,但它认为实例还是健康的,eureka会保护这些实例,不会把它们从注册表中删掉。

该保护机制的目的是避免网络连接故障,在发生网络故障时,微服务和注册中心之间无法正常通信,但服务本身是健康的,不应该注销该服务,如果eureka因网络故障而把微服务误删了,那即使网络恢复了,该微服务也不会重新注册到eureka server了,因为只有在微服务启动的时候才会发起注册请求,后面只会发送心跳和服务列表请求,这样的话,该实例虽然是运行着,但永远不会被其它服务所感知。所以,eureka server在短时间内丢失过多的客户端心跳时,会进入自我保护模式,该模式下,eureka会保护注册表中的信息,不在注销任何微服务,当网络故障恢复后,eureka会自动退出保护模式。自我保护模式可以让集群更加健壮。

但是我们在开发测试阶段,需要频繁地重启发布,如果触发了保护机制,则旧的服务实例没有被删除,这时请求有可能跑到旧的实例中,而该实例已经关闭了,这就导致请求错误,影响开发测试。所以,在开发测试阶段,我们可以把自我保护模式关闭,只需在eureka server配置文件中加上如下配置即可:

#eureka基本配置信息
eureka:client:service-url:#Eureka 客户端与 Eureka 服务端进行交互的地址defaultZone: http://127.0.0.1:${server.port}/eureka#是否将自己注册到Eureka服务中,本身就是注册中心所以无需注册register-with-eureka: false#是否从Eureka中检索注册信息,本身就是注册中心所以无需检索fetch-registry: falseserver:# 测试时关闭自我保护机制,保证不可用服务及时踢出enable-self-preservation: false##剔除失效服务间隔eviction-interval-timer-in-ms: 2000

在eureka client配置文件中加上:

#eureka基本配置信息
eureka:client:service-url:#Eureka 客户端与 Eureka 服务端进行交互的地址defaultZone: http://127.0.0.1:8100/eureka/# 心跳检测检测与续约时间# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务instance:# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)lease-renewal-interval-in-seconds: 1# Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)lease-expiration-duration-in-seconds: 2

但在生产环境,不会频繁重启,所以,一定要把自我保护机制打开,否则网络一旦中断,就无法恢复。
当然关于自我保护还有很多个性化配置,这里不详细说明。

注意考虑网络不可达情况下:调用接口幂等、重试、补偿等。

创建工程
1. 目前工程结构
image
2. 首先创建父工程springcloud,以后这个工程下存放子工程eureka,feign,zuul等组件

将该工程的src文件夹删除,在pom文件中添加依赖

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.1.RELEASE</version><relativePath ></relativePath></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><!--引用仓库--><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url><snapshots><enabled>false</enabled></snapshots></repository></repositories><!--管理依赖,子项目中的依赖不用列出版本号--><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Finchley.M9</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
创建eureka父工程

新建springcloud-eureka项目,在pom文件中添加依赖

    <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies>
创建eureka服务端

以springcloud-eureka为父工程,新建springboot-eureka-server项目,这里不需要添加eureka-server依赖,因为父工程中有了。

1. 添加配置

在resources目录中添加application.yml文件,在文件中添加配置

#服务端口号
server:port: 8100spring:application:name: eureka-server#eureka基本配置信息
eureka:client:service-url:#Eureka 客户端与 Eureka 服务端进行交互的地址defaultZone: http://127.0.0.1:${server.port}/eureka#是否将自己注册到Eureka服务中,本身就是注册中心所以无需注册register-with-eureka: false#是否从Eureka中检索注册信息,本身就是注册中心所以无需检索fetch-registry: falseserver:# 测试时关闭自我保护机制,保证不可用服务及时踢出enable-self-preservation: false##剔除失效服务间隔eviction-interval-timer-in-ms: 2000
2. 启动类

java目录下创建com.lxg二级目录,然后创建EurekaServerApp启动类

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

在类上加EnableEurekaServer注解,启动EurekaServer。

创建eureka客户端

以springcloud-eureka为父工程,新建springboot-eureka-client项目。在pom文件中添加依赖:

    <dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies>
1. 添加配置

在resources目录中添加application.yml文件,在文件中添加配置

#端口号
server:port: 9100spring:application:name: eureka-client#eureka基本配置信息
eureka:client:service-url:#Eureka 客户端与 Eureka 服务端进行交互的地址defaultZone: http://127.0.0.1:8100/eureka/# 心跳检测检测与续约时间# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务instance:# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)lease-renewal-interval-in-seconds: 1# Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)lease-expiration-duration-in-seconds: 2
2. 启动类

java目录下创建com.lxg二级目录,然后创建EurekaClientApp启动类,这里启动类名称不能为EurekaClient,否则会起冲突导致启动失败。类上使用EnableEurekaClient注解。

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

先启动服务端,再启动客户端,访问127.0.0.1:8100 ,访问监控页面。


image

图中的红色字体是在提示已经关闭了eureka的自我保护机制,此时如果关闭客户端,页面中的服务就会被踢出,如果没有关闭的话,即使客户端关闭了,服务依然会存在。

高可用注册中心(Eureka集群)

在微服务中,注册中心非常核心,可以实现服务治理,如果一旦注册出现故障的时候,可能会导致整个微服务无法访问,在这时候就需要对注册中心实现高可用集群模式。

Eureka高可用原理

默认情况下Eureka是让服务注册中心,不注册自己,但是在集群中,需要设置能注册自己,因为这两个属性默认为true,只需要不写就行了。

###使该注册中心注册自己register-with-eureka: true
###需要去注册中心上检索服务fetch-registry: true

Eureka高可用实际上将自己作为服务向其他服务注册中心注册自己,这样就可以形成一组相互注册的服务注册中心,从而实现服务清单的互相同步,达到高可用效果。

Eureka集群环境搭建

新增server1,server2,server3三个节点。


image

server1配置:

#服务端口号
server:port: 8100spring:application:name: eureka-server#eureka基本配置信息
eureka:client:service-url:#Eureka 客户端与 Eureka 服务端进行交互的地址defaultZone: http://127.0.0.1:8200/eureka,http://127.0.0.1:8300/eurekaserver:# 测试时关闭自我保护机制,保证不可用服务及时踢出enable-self-preservation: false##剔除失效服务间隔eviction-interval-timer-in-ms: 2000

server2配置:

#服务端口号
server:port: 8200spring:application:name: eureka-server#eureka基本配置信息
eureka:client:service-url:#Eureka 客户端与 Eureka 服务端进行交互的地址defaultZone: http://127.0.0.1:8100/eureka,http://127.0.0.1:8300/eurekaserver:# 测试时关闭自我保护机制,保证不可用服务及时踢出enable-self-preservation: false##剔除失效服务间隔eviction-interval-timer-in-ms: 2000

server3配置:

#服务端口号
server:port: 8300spring:application:name: eureka-server#eureka基本配置信息
eureka:client:service-url:defaultZone: http://127.0.0.1:8100/eureka,http://127.0.0.1:8200/eurekaserver:# 测试时关闭自我保护机制,保证不可用服务及时踢出enable-self-preservation: false##剔除失效服务间隔eviction-interval-timer-in-ms: 2000

然后修改客户端的配置,因为以前是单个eureka注册中心,只需要注册进一个地址就行了,现在要注册进所有的注册中心。

#端口号
server:port: 9100spring:application:name: eureka-client#eureka基本配置信息
eureka:client:service-url:#Eureka 客户端与 Eureka 服务端进行交互的地址#单机#defaultZone: http://127.0.0.1:8100/eureka/#集群defaultZone: http://127.0.0.1:8100/eureka/,http://127.0.0.1:8200/eureka/,http://127.0.0.1:8300/eureka/# 心跳检测检测与续约时间# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务instance:# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)lease-renewal-interval-in-seconds: 1# Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)lease-expiration-duration-in-seconds: 2

先启动所有的服务端节点,再启动客户端。访问localhost:8100 ,localhost:8200 ,localhost:8300 都能进入eureka的界面,同时看到客户端服务和其他的注册中心。这个时候即使有某一个节点挂了,服务依然是可用的,而且性能肯定比单机版要好。

搭建eureka集群有几点需要注意的:

1.与先前独立运行注册不同,注意defaultZone属性,它的值为除了自己以外的所有eureka节点的地址,以英文逗号分割。
2.去掉fetch-registry 与 register-with-eureka配置(其实这样做就会取对应的默认值,两个值均为true),需要让自己能被注册和检索。
3.启动第一个注册中心时会报Cannot execute request on any known server的错误,暂时不管它,实际上eureka注册中心的ui界面是能打开的,当所有的节点启动完毕,就能找到服务,此错误就会消失。
4.所有注册中心的节点的spring.application.name必须保持一致。
5.当客户端需要往注册中心集群注册服务时defaultZone属性需要把所有节点地址都加上,如果像单节点一样的话,你连接的那个节点挂了,集群中其他节点就无法获取到该服务,也就不能达到高可用。

本文GitHub源码:https://github.com/lixianguo5097/springcloud/tree/master/springcloud-eureka

CSDN:https://blog.csdn.net/qq_27682773
简书:https://www.jianshu.com/u/e99381e6886e
博客园:https://www.cnblogs.com/lixianguo

最后编辑于:2024-09-18 20:52:00


喜欢的朋友记得点赞、收藏、关注哦!!!


http://www.ppmy.cn/news/1528124.html

相关文章

【数据结构】什么是二叉搜索(排序)树?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;二叉搜索(排序)树的概念 &#x1f4cc;二叉搜索(排序)树的操作 &#x1f38f;二叉搜索树的查找 &#x1f38f;二叉搜索树的插入 &#x1f38f;二叉搜索树的…

MYSQL面试知识点手册

第一部分&#xff1a;MySQL 基础知识 1.1 MySQL 简介 MySQL 是世界上最流行的开源关系型数据库管理系统之一&#xff0c;它以性能卓越、稳定可靠和易用性而闻名。MySQL 主要应用在 Web 开发、大型互联网公司、企业级应用等场景&#xff0c;且广泛用于构建高并发、高可用的数据…

SDL 2.0视频数据渲染到窗口上播放流程

在 SDL 2.0 中&#xff0c;将视频数据渲染到窗口上涉及几个步骤&#xff0c;包括创建窗口和渲染器、加载视频帧数据、将其绘制到纹理上以及更新显示。以下是一个基本的示例&#xff0c;演示了如何使用 SDL 2.0 渲染视频帧到窗口&#xff1a; 基本步骤 初始化 SDL&#xff1a;…

【结构型】树形结构的应用王者,组合模式

目录 一、组合模式1、组合模式是什么&#xff1f;2、组合模式的主要参与者&#xff1a; 二、优化案例&#xff1a;文件系统1、不使用组合模式2、通过组合模式优化上面代码优化点&#xff1a; 三、使用组合模式有哪些优势1、统一接口&#xff0c;简化客户端代码2、递归结构处理方…

【大模型入门】零基础入门AI大模型应用开发,你需要一个系统的入门路径!

随着大模型技术的飞速发展&#xff0c;我们正站在一个全新的技术前沿&#xff0c;探索着如何将这些强大的工具应用于实际问题的解决。如果你对AI大模型应用开发充满热情&#xff0c;那么你可以读一下这篇文章——一个系统全面的入门指南&#xff0c;专为渴望深入AI世界的你设计…

贪心算法day31|56. 合并区间、738. 单调递增的数字(整数与字符串的转换)、贪心刷题总结

贪心算法day31|56. 合并区间、738. 单调递增的数字、贪心刷题总结 56. 合并区间738. 单调递增的数字贪心刷题总结 56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 …

ffmpeg实现视频的合成与分割

视频合成与分割程序使用 作者开发了一款软件&#xff0c;可以实现对视频的合成和分割&#xff0c;界面如下&#xff1a; 播放时&#xff0c;可以选择多个视频源&#xff1b;在选中“保存视频”情况下&#xff0c;会将多个视频源合成一个视频。如果只取一个视频源中一段视频…

python + ssh+ rich 升级和备份脚本

升级版本 &#xff08;根据AI提供的脚本,修改后&#xff09; import os import paramiko from scp import SCPClient from rich.progress import (BarColumn,DownloadColumn,Progress,TaskID,TextColumn,TimeRemainingColumn,TransferSpeedColumn, )def get_file_size(file_pat…