Spring Cloud第十一篇 | 分布式配置中心高可用
本文是Spring Cloud专栏的第十一篇文章,了解前十篇文章内容有助于更好的理解本文:
一、前言
为了保证配置中心服务的高可用,将配置中心服务端做成一个微服务,将其集群化,从而达到高可用,当你部署了多个Config Server实例并预期一个或多个实例不时不可用时,为确保高可用性,你可以指定多个URL(作为spring.cloud.config.uri属性下的逗号分隔列表),也可以让所有实例在Eureka等Service Registry中注册(如果使用发现优先Bootstrap模式)。注意:只有在Config Server未运行时(即应用程序已退出时)或发生连接超时时,才能确保高可用性,例如:如果Config Server返回500(内部服务器错误)响应或Config Client从Config Server收到401(由于凭据错误或其他原因),则Config Client不会尝试从其他URL获取属性,这种错误表示用户问题而不是可用性问题。
上一篇文章《Spring Cloud第十篇 | 分布式配置中心Config》讲述了一个服务如何从配置中心读取文件,上一篇案例只是通过client直接访问server,地址直接写死,这种方式显然不够灵活,当服务实例很多时,都从配置中心读取文件,如果配置中心服务端地址变动的话,那我们所有的服务都启动不起来了,都需要变更配置中心服务端地址,特别麻烦,由于微服务使用了注册中心,以及注册中心的优点等,我们可以结合Eureka注册中心,将配置中心做成微服务,将其集群化部署,达到配置中心的高可用,架构图如下:
二、改造配置中心服务端
1、添加注册中心客户端依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、主启动类上添加注解@EnableEurekaClient
3、在application.yml文件中添加Eureka相关配置
eureka:
client:
service-url:
defaultZone: http://localhost:8700/eureka
#客户端每隔30秒从Eureka服务上更新一次服务信息
registry-fetch-interval-seconds: 30
#需要将我的服务注册到eureka上
register-with-eureka: true
#需要检索服务
fetch-registry: true
#心跳检测检测与续约时间
instance:
#告诉服务端,如果我10s之内没有给你发心跳,就代表我故障了,将我剔除掉,默认90s
#Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒,超过则剔除(客户端告诉服务端按照此规则等待自己)
lease-expiration-duration-in-seconds: 10
#每隔2s向服务端发送一次心跳,证明自已依然活着,默认30s
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(客户端告诉服务端自己会按照该规则)
lease-renewal-interval-in-seconds: 2
# 启用ip配置 这样在注册中心列表中看见的是以ip+端口呈现的
prefer-ip-address: true
# 实例名称 最后呈现地址:ip:2002
instance-id: ${spring.cloud.client.ip-address}:${server.port}
4、然后启动config server服务端就行了
三、改造配置中心客户端
1、改造步骤同1-1,1-2,1-3,然后在application.yml文件中将spring.cloud.config配置修改为如下样子
spring:
cloud:
config:
#uri则表示配置中心的地址
#uri: http://localhost:8888
#注:config 客户端在没有 spring.cloud.config.name属性的时候,服务端{application} 获取的是客户端
#spring.application.name的值,否则,获取的是 spring.cloud.config.name的值。
#1)、当没有spring.cloud.config.name时,客户端获取的是spring.application.name 所对应的git库中的文件,并且只能获取一个文件
#2)、当一个项目中有需求要获取多个文件时,就需要用到spring.cloud.config.name这个属性,以逗号分割
name: configclient
profile: dev
#label对应了label部分
label: master
discovery:
#表示开启通过服务名来访问config-server
enabled: true
#则表示config-server的服务名
service-id: tmgsp-config-server
2、查看注册中心上注册的服务
3、然后访问http://localhost:8881/index可以看到相同效果,如果需要配置中心高可用,只需要将配置中心启动多个实例就行了。
四、失败快速响应与重试
1、失败快速响应
Spring Cloud Config的客户端会预先加载很多其他信息,然后再开始连接Config Server进行属性的注入。不作任何额外配置的情况下,失败响应有点迟钝,举个简单的例子,关掉config-server,我们直接启动config-client,此时启动会报错,但是报错时间较晚,当我们构建的应用较为复杂的时候,可能在连接Config Server之前花费较长的启动时间,而在一些特殊场景下,我们又希望可以快速知道当前应用是否能顺利地从Config Server获取到配置信息,这对在初期构建调试环境时,可以减少很多等待启动的时间。要实现客户端优先判断Config Server获取是否正常,并快速响应失败内容,只需在Config客户端的bootstrap.yml中配置参数spring.cloud.config.failFast=true即可。
此时不启动config-server直接启动config-client依然会报错,但是我们看到报错时间较早,系统都没打印几条启动日志。
2、重试
上面我们提过了当Config Server宕机或是客户端配置不正确导致连接不到Config Server而启动失败的情况,快速响应的配置可以发挥比较好的效果。但是,如果网络波动等其他间歇性原因导致的问题,直接启动失败似乎代价有些高。所以Config客户端还提供了自动重试的功能,在开启重试功能前,先确保已经配置了(确保开启失败快速响应)spring.cloud.config.failFast=true在进行下面操作。
2-1、在客户端添加依赖
<!--连接config-server重试机制相关依赖-->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2-2、不需要再做其他任何配置,启动客户端应用,在控制台中可以看到如下内容。客户端在连接Config Server失败之后,会继续尝试,直到第6次失败后,才返回错误信息。通过这样的重试机制,可以避免一些间歇性问题引起的失败导致客户端应用无法启动的情况。查看日志如下,测试的时候切记Config Server需要在注册中心没有剔除掉,要是剔除掉那就没的说了。
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://172.20.10.2:8888/
INFO 9996 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SPRINGCLOUD-CONFIG-CLIENT/172.20.10.2:8881 - Re-registering apps/SPRINGCLOUD-CONFIG-CLIENT
INFO 9996 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SPRINGCLOUD-CONFIG-CLIENT/172.20.10.2:8881: registering service...
INFO 9996 --- [tbeatExecutor-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_SPRINGCLOUD-CONFIG-CLIENT/172.20.10.2:8881 - registration status: 204
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://172.20.10.2:8888/. Will be trying the next url if available
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://172.20.10.2:8888/
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://172.20.10.2:8888/. Will be trying the next url if available
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://172.20.10.2:8888/
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://172.20.10.2:8888/. Will be trying the next url if available
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://172.20.10.2:8888/
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://172.20.10.2:8888/. Will be trying the next url if available
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://172.20.10.2:8888/
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://172.20.10.2:8888/. Will be trying the next url if available
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://172.20.10.2:8888/
INFO 9996 --- [ main] c.c.c.ConfigServicePropertySourceLocator : Connect Timeout Exception on Url - http://172.20.10.2:8888/. Will be trying the next url if available
ERROR 9996 --- [ main] o.s.boot.SpringApplication : Application run failed
2-3、从日志上可以看出Config client一共尝试了六次去访问Config server,六次都失败了才抛异常和重试机制相关的配置有如下四个:
# 配置重试次数,默认为6
spring.cloud.config.retry.max-attempts=6
# 间隔乘数,默认1.1
spring.cloud.config.retry.multiplier=1.1
# 初始重试间隔时间,默认1000ms
spring.cloud.config.retry.initial-interval=1000
# 最大间隔时间,默认2000ms
spring.cloud.config.retry.max-interval=2000
五、动态刷新配置
1、有的时候,我动态的更新了Git仓库中的配置文件,那么我如何让我的config-client能够及时感知到呢?方式很简单,首先在config-client中添加如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
由于我们父模块(springcloud-learn)依赖中已经引入该依赖,所以可以省略不引入。
该依赖中包含了/refresh端点的实现,我们将利用这个端点来刷新配置信息。
2、在需要刷新的Bean上添加@RefreshScope注解,不然客户端不知道刷新哪里
3、然后需要在application.yml中配置暴露/refresh端点
management:
endpoints:
web:
exposure:
include: ["info","health","refresh"]
4、然后启动访问http://localhost:8881/index
5、修改码云上的configclient-dev.yml文件,因为我们客户端加载的是这个配置文件
6、然后用postman工具向http://localhost:8881/actuator/refresh地址发送POST请求(该端点只接受post请求,日志上可以看出),结果如下:
7、重新访问http://localhost:8881/index显示内容如下
详细参考案例源码:https://gitee.com/coding-farmer/springcloud-learn
Spring Cloud第十一篇 | 分布式配置中心高可用的更多相关文章
- Spring Cloud第十篇 | 分布式配置中心Config
本文是Spring Cloud专栏的第十篇文章,了解前九篇文章内容有助于更好的理解本文: Spring Cloud第一篇 | Spring Cloud前言及其常用组件介绍概览 Spring Clo ...
- Spring Cloud config之一:分布式配置中心入门介绍
Spring Cloud Config为服务端和客户端提供了分布式系统的外部化配置支持.配置服务器为各应用的所有环境提供了一个中心化的外部配置.它实现了对服务端和客户端对Spring Environm ...
- Spring Cloud Config 1 (分布式配置中心)
spring cloud config是spring cloud团队创建的一个全新的项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端和客户端两部分. 服务端也被称为 ...
- Spring Cloud (6) 分布式配置中心-高可用
高可用 现在已经可以从配置中心读取配置文件了,当微服务很多时都从配置中心读取配置文件,这时可以将配置中心做成一个微服务,将其集群化,从而达到高可用. 改造config-server 加入eureka ...
- SpringCloud微服务实战一:Spring Cloud Eureka 服务发现与注册中心(高可用实列为两个注册中心)
微服务架构: 微服务架构的核心思想是,一个应用是由多个小的.相互独立的.微服务组成,这些服务运行在自己的进程中,开发和发布都没有依赖.不同服务通过一些轻量级交互机制来通信,例如 RPC.HTTP 等, ...
- spring cloud 学习(2) - eureka server注册中心高可用及安全认证
接上节继续,注册中心单点肯定是不牢靠的,可以参考下面的方案做成注册中心集群: 弄成3个节点,每个节点向其它节点注册,这样只要集群中有一个节点正常工作即可.为了方便在本机弄出这种效果,我们先修改下hos ...
- 第六篇: 分布式配置中心(Spring Cloud Config)
一.简介 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件. 在Spring Cloud中,有分布式配置中心组件spring cloud confi ...
- SpringCloud教程 | 第六篇: 分布式配置中心(Spring Cloud Config)
一.简介 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件.在Spring Cloud中,有分布式配置中心组件spring cloud config ...
- 史上最简单的SpringCloud教程 | 第六篇: 分布式配置中心(Spring Cloud Config)
一.简介 在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件. 在Spring Cloud中,有分布式配置中心组件spring cloud confi ...
随机推荐
- HTML的footer置于页面最底部
vue项目中,使用element-ui的布局,仍然出现footer不固定页面底部的情况,网上找到的一个管用的 方法是:footer高度固定+绝对定位 <html> <head> ...
- 编译k8s1.11 kube-apiserver源码
说明 修改k8s1.11 kube-apiserver源码并构建成镜像,最终替换运行在集群中的kube-apiserver pod来验证本次源码修改 参看链接:https://xinchen.blog ...
- Docker-Compose基础与实战,看这一篇就够了
what & why Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排.使用前面介绍的Dockerfile我们很容易定义一个单独的应用容器.然 ...
- 设计模式之美学习(九):业务开发常用的基于贫血模型的MVC架构违背OOP吗?
我们都知道,很多业务系统都是基于 MVC 三层架构来开发的.实际上,更确切点讲,这是一种基于贫血模型的 MVC 三层架构开发模式. 虽然这种开发模式已经成为标准的 Web 项目的开发模式,但它却违反了 ...
- 【前端】 在前端利用数学函数知识+box-shadow解波浪图形
序 今天正在刷数学函数相关题目,刷到了下面这篇文章,哇哦-有意思. 利用cos和sin实现复杂的曲线.传送门在下面. CSS 技巧一则 -- 在 CSS 中使用三角函数绘制曲线图形及展示动画 正巧在复 ...
- solr数据操作
本文介绍solr的基本数据操作,基于solr 8.2.solr支持多种数据格式,包括XML,JSON,CSV等,并提供多种脚本和工具来操作数据.本文讲解curl请求和JSON数据格式的处理方式. 本文 ...
- 通过Python将Excel表格信息导入数据库
前言 公司原采用Excel表格方式记录着服务器资产信息,随着业务的增加,相应的硬件资产也增加,同时物理机虚拟化出多台虚拟机,存在表格管理杂乱.变更资产信息不能及时相互同步, 为了紧跟时代的步伐,老大搞 ...
- java面试常见题目
JAVA相关基础知识面向对象的特征有哪些方面 1.抽象:抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并不打算了解全部问题,而只是选择其中的一部分,暂时不用 ...
- 英语口语考试资料Volunteers
Being a volunteer is great! There are lots of volunteers around us now. And they don’t do it ...
- 关于servlet报错和jsp中报关于servlet的错误
servlet-api是对servlet的支持,如果你导入别人的项目后出现servlet中的导包处出现关于javax.servlet.的错误,那么就是缺少这个包了.还有对jsp页面中的报错的支持. 下 ...