当前位置: 首页 > news >正文

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

前言

本篇文章主要介绍的是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.mrgr.cn/news/30303.html

相关文章:

  • git上feature合并到development分支
  • WebRTC视频 01 - 视频采集整体架构
  • 平安人寿山西分公司:践行绿色金融,开启绿色新篇章
  • Python用CEEMDAN-LSTM-VMD金融股价数据预测及SVR、AR、HAR对比可视化
  • 【神经科学学习笔记】基于分层嵌套谱分割(Nested Spectral Partition)模型分析大脑网络整合与分离的局部指标(二)
  • 基于Java+SpringBoot+Vue前后端分离电影院管理系统
  • 组件封装有哪些注意事项—面试常问优美回答
  • csgo使用服务器一键开服联机
  • Vue2+vue-office/excel 实现在线加载Excel文件预览
  • 图的数据结构定义
  • 音视频入门基础:AAC专题(9)——FFmpeg源码中计算AAC裸流每个packet的duration和duration_time的实现
  • maxwell 输出消息到 redis
  • 微信小程序页面制作——婚礼邀请函(含代码)
  • Java线程---并发集合
  • Git(4):修改git提交日志
  • 3D虚拟商城是什么?有哪些优势?
  • 关于文件操作
  • SQL建表、条件查询、插入数据、更新数据、删除数据、添加字段。
  • 免费开源微信机器人 教程/文档/开发
  • 前端开发规范
  • PCIe扫盲(九)
  • 集运系统核心功能模块:打造高效集运仓日常管理
  • Dubbo与SpringCloud的区别和优缺点
  • 2024/9/19 408大题专训之五段式指令流水线题型总结
  • Android 新增目录怎么加入git
  • 相亲交易系统源码详解与开发指南