SpringCloud Config应用
本文通过搭建一个eureka注册中心,config配置中心,以及两个configclient客户端来演示springlcoud config的基本使用以及通过spring cloud config bus来实现配置项的动态刷新。
1.项目搭建
1.1父项目
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR4</spring-cloud.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
</properties>
<modules>
<module>spring-cloud-eureka-server-9090</module>
<module>spring-cloud-config-server-9091</module>
<module>spring-cloud-user-service-8081</module>
<module>spring-cloud-order-service-8082</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- import 导入springboot springcloud的依赖包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
1.2 注册中心搭建
spring-cloud-eureka-server-9090 ,引入eureka 依赖:spring-cloud-starter-netflix-eureka-server
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.gupaoedu.example</groupId>
<artifactId>spring-cloud-eureka-server-9090</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-eureka-server-9090</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 注册中心application.properties 配置
spring.application.name=spring-cloud-eureka-server-9090
server.port=9090
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone=http://localhost:9090/eureka
- @EnableEurekaServer开启注册中心
package com.gupaoedu.example.springcloudeurekaserver9090;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class SpringCloudEurekaServer9090Application {
public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaServer9090Application.class, args);
}
}
1.3 配置中心搭建
搭建配置中心,需要引入如下依赖:
- spring-cloud-config-server 配置中心服务端
- spring-cloud-starter-netflix-eureka-client 配置中心需要作为eureka客户端注册到注册中心
- spring-boot-starter-actuator 手动刷新配置项
- spring-cloud-config-monitor 自动刷新配置项
- spring-cloud-starter-bus-kafka 使用kafka作为springcloud config bus消息总线
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.gupaoedu.example</groupId>
<artifactId>spring-cloud-config-server-9091</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-config-server-9091</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- 注册到注册中心,需要添加依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 测试kafka作为分布式配置中心的消息总线,configserver以及configclient都需要添加cloud-bus以及actuator依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-actuator</artifactId>-->
<!-- </dependency>-->
<!-- 需要把spring-boot-starter-actuator依赖去掉,否则configclient无法连接到配置中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
</dependencies>
</project>
- 分布式配置中心需要依赖一个外部件来存储各个配置项,这里选择gitee作为配置项的持久化存储
在gitee上面创建一个仓库spring-cloud-config-server ,并设置“是否开源” 为公开的,否则会报Authentication is required but no CredentialsProvider has been registered 这种错误。
- 配置中心
spring:
application:
name: spring-cloud-config-server-9091
cloud:
config:
server:
git:
uri: https://gitee.com/liuch890228/spring-cloud-config-server.git
search-paths: spring-cloud-config-server
bus:
enabled: true # 开启bus
trace:
enabled: true
refresh:
enabled: true
kafka:
bootstrap-servers: localhost:9092 #kafka地址
consumer:
group-id: config-server # 分组,不同的组可以收到相同的消息
server:
port: 9091
eureka:
client:
service-url:
defaultZone: http://localhost:9090/eureka
#kafka
# 通过bus刷新外部配置
# 通过调用/actuator/refresh接口刷新配置
management:
endpoints:
web:
exposure:
include: bus-refresh
-
kafka安装与启动
见windows安装kafka -
开启配置中心configserver和eurekaclient
package com.gupaoedu.example.springcloudconfigserver9091;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableConfigServer
@EnableEurekaClient
@SpringBootApplication
public class SpringCloudConfigServer9091Application {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConfigServer9091Application.class, args);
}
}
1.4 order-service搭建
1.4.1 ordre-service 父项目
<?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">
<modelVersion>4.0.0</modelVersion>
<!-- 添加父pom依赖,这样user-service-provider项目能够直接依赖到spring-cloud-netflix根项目依赖的jar包 -->
<parent>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-order-service-8082</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>order-service-api</module>
<module>order-service-provider</module>
</modules>
<name>spring-cloud-order-service-8082</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
</project>
1.4.2 order-service-api 子项目
- 加入spring-cloud-starter-openfeign 依赖,对外提供Feign接口定义
<?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>spring-cloud-order-service-8082</artifactId>
<groupId>com.gupaoedu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>order-service-api</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
</project>
- API接口定义
package com.gupaoedu.springcloud;
import com.gupaoedu.springcloud.dto.OrderDto;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
public interface OrderService {
@GetMapping("/orders")
String orders();
@PostMapping("/order")
int insert(OrderDto dto); // OrderDto 一个属性 String orderId
}
openFeign接口定义
package com.gupaoedu.springcloud.clients;
import com.gupaoedu.springcloud.OrderService;
import org.springframework.cloud.openfeign.FeignClient;
@FeignClient("order-service")
public interface OrderServiceFeignClient extends OrderService{
}
1.4.3 order-service-provider 子项目
- 提供openfeign接口的实现需要添加下面的依赖
spring-cloud-starter-config
spring-cloud-starter-netflix-eureka-client 注册到注册中心
spring-cloud-config-client 从configserver读取配置信息
pring-boot-starter-actuator 提供刷新配置的监控功能
spring-cloud-starter-bus-kafka 使用kafka作为springcloud config 分布式配置中心的消息总线
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-order-service-8082</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.gupaoedu.example</groupId>
<artifactId>order-service-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>order-service-provider</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>order-service-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 测试kafka作为分布式配置中心的消息总线-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<dependency>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>order-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
- bootstrap.yml启动配置
# 外部化配置,放到bootstrap.yml中优先加载!!!
spring:
cloud:
config:
discovery:
enabled: true
service-id: spring-cloud-config-server-9091
eureka:
client:
service-url:
defaultZone: http://localhost:9090/eureka
- 常规配置
spring:
application:
name: order-service
cloud:
bus:
enabled: true
trace:
enabled: true
refresh:
enabled: true
kafka:
bootstrap-servers: localhost:9092 #kafka地址
consumer:
group-id: order-service # 分组,不同的组可以收到相同的消息
server:
port: 8082
# 1.添加springboot-starter-actuator依赖; # 2.开放自动刷新端点,同时还需要在刷新配置的地方加上@Refresh注解
# 3.通过调用/actuator/refresh接口刷新配置
management:
endpoints:
web:
exposure:
include: refresh
- 启动类
package com.gupaoedu.example.orderserviceprovider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
// controller包不是OrderServiceProviderApplication所在的子包,需要指定包扫描路径。
@ComponentScan(basePackages="com.gupaoedu.example.controller")
@EnableEurekaClient
@SpringBootApplication
public class OrderServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceProviderApplication.class, args);
}
}
- order-service openfeign接口实现
package com.gupaoedu.example.orderserviceprovider;
import com.gupaoedu.springcloud.OrderService;
import com.gupaoedu.springcloud.dto.OrderDto;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderServiceImpl implements OrderService {
@Override
public String orders() {
return "Return All Orders";
}
@Override
public int insert(OrderDto dto) {
return 0;
}
}
- 配置项测试类
package com.gupaoedu.example.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RefreshScope // 配置项有更新后,重新读取新的配置项
@RestController
public class ConfigController {
@Value("${hello}")
private String txt;
@GetMapping("/config")
public String config(){
return txt;
}
}
1.5 user-service搭建
1.5.1 user-service 父项目
<?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">
<modelVersion>4.0.0</modelVersion>
<!-- 添加父pom依赖,这样user-service-provider项目能够直接依赖到spring-cloud-netflix根项目依赖的jar包 -->
<parent>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-netflix</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.gupaoedu.springcloud</groupId>
<artifactId>spring-cloud-user-service-8081</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>user-service-api</module>
<module>user-service-provider</module>
</modules>
</project>
1.5.2 user-service API接口
<?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>spring-cloud-user-service-8081</artifactId>
<groupId>com.gupaoedu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-service-api</artifactId>
</project>
1.5.3 user-service 服务实现
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>spring-cloud-user-service-8081</artifactId>
<groupId>com.gupaoedu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.gupaoedu.example</groupId>
<artifactId>user-service-provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>user-service-provider</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- user-service 项目配置
(1) 启动配置bootstrap.yml
user-service 作为configserver的客户端,在启动时需要从配置中心获取外部配置,这个步骤需要在启动时完成,因此,注册中心eureka和配置中心configserver的相关配置要放到bootstrap.yml中去,否则项目启动会报错
spring:
cloud:
config:
discovery:
enabled: true # 不写默认是false,从8088端口查询外部配置项
service-id: spring-cloud-config-server-9091
eureka:
client:
service-url:
defaultZone: http://localhost:9090/eureka
(2)application.yml
spring:
application:
name: user-service
cloud:
bus:
enabled: true
trace:
enabled: true
refresh:
enabled: true
kafka:
bootstrap-servers: localhost:9092 #kafka地址
consumer:
group-id: user-service # 分组,不同的组可以收到相同的消息
server:
port: 8081
# 刷新外部配置
# 1.添加springboot-starter-actuator依赖; # 2.开放自动刷新端点,同时还需要在刷新配置的地方加上@Refresh注解
# 3.通过调用/actuator/refresh接口刷新配置
management:
endpoints:
web:
exposure:
include: refresh
- 配置项读取测试代码
package com.gupaoedu.example.userserviceprovider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages ="com.gupaoedu.example" )
@EnableEurekaClient
@SpringBootApplication
public class UserServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceProviderApplication.class, args);
}
}
package com.gupaoedu.example.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope // 动态刷新配置
@RequestMapping("/user")
public class ConfigController {
@Value("${env}")
private String text;
@GetMapping("/config")
public String getText(){
return text;
}
}
2 SpringCloud config配置应用
2.1 springcloud配置文件后缀组合方式
- /{application}/{profile}/{label}
- /{application}-profile
- /{label} / {application} -{profile}
application: 应用名称
profile: 不同的配置分组
在gitee上添加如下几个配置文件:
order-service.yml
env:
test
hello:
mike666
user-service.properties

spring.application.name=user-service
server.port=8081
env=user-test12345
user-service-prd.properties
env=prd
timer.switch=off
user-service-dev.properties
env=dev
依次启动zookeeper ,kafka eureka-server ,config-server ,order-service ,user-service, 演示 /{application}-profile 这种后缀组合的效果:
先访问http://localhost:9091/user-service.properties,结果如下
访问 http://localhost:9091/user-service-prd.properties ,springcloud会自动合并user-service.properties 和user-service-prd.properties中的配置:
除此之外,它还可以支持以json , yml 格式读取配置:
2.2 spring-boot-starter-actuator 手动刷新配置
将configserver项目pom.xml文件中的spring-cloud-config-monitor和 spring-cloud-starter-bus-kafka的依赖注释掉,只用spring-boot-starter-actuator 来刷新配置项
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
这时如果git上的配置项有更新,configclient端要想更新配置项,必须要手动发送一个post请求给对应的项目的/actuator/refresh接口,才能读取到最新的配置。这种方式有个缺点,就是如果有几十个微服务,每个微服务都需要单独去调用/actuator/refresh接口更新配置才行。
2.3 springcloud config bus + webhook自动刷新配置
通过消息总线实现配置自动刷新,它的原理是当configserver上的配置有了更新,它会发送一个广播消息到消息队列中(kafka rabbitmq等),所有的configclient 会去订阅这些消息然后更新自己本地缓存的配置项,从而实现配置项的刷新。
如果引入spring-cloud-starter-bus-kafka 依赖,并启动kafka,此时又会出现一个问题:
修改了配置项之后用postman刷新总线消息:POST http://localhost:9091/actuator/bus-refresh, 虽然实现了对各个configclient 的配置项进行批量刷新,不需要对每个微服务项目单独调用actuator接口去点对点的同步配置项, 但是它仍然是手动的。有没有办法实现配置项变化自动去刷新呢? git的webhook功能就具备这个功能。通过webhook自动刷新配置,需要一个内网穿透工具,因为git无法直接访问到本地的localhost 地址,需要借助内网穿透工具webhook来让git 能够访问到localhost ,它的实现是 ,一旦webhook检测到配置更新的pull、request事件,就会去调用webhook中配置的地址去更新配置项:
首先启动ngrok
然后配置webhook
configserver引入spring-cloud-starter-bus-kafka 的依赖 ,然后启动erureka configserver , 以及configclient,这时修改gitee上的配置项,会看到项目中报错了:
2020-12-25 08:15:25.688 WARN 1356 --- [io-9091-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_ARRAY token
at [Source: (PushbackInputStream); line: 1, column: 315] (through reference chain: java.util.LinkedHashMap["commits"])]
2020-12-25 08:15:26.109 WARN 1356 --- [nio-9091-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
at [Source: (PushbackInputStream); line: 1, column: 54] (through reference chain: java.util.LinkedHashMap["pull_request"])]
无法解析json, 这是因为git发送的报文 无法被正确解析,webhook上面要改用monitor接口!需要在configserver中加入spring-cloud-config-monitor的依赖(configclient pom不用修改)
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!-- 注册到注册中心,需要添加依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 测试kafka作为分布式配置中心的消息总线,configserver以及configclient都需要添加cloud-bus以及actuator依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-actuator</artifactId>-->
<!-- </dependency>-->
<!-- http://04b6c5e91673.ngrok.io/monitor 通过ngrok映射到本地9091 configserver调用/monitor接口,
不会出现/actuator/bus-refresh接口推送配置项变更时json请求无法被config client解析的情况 -->
<!-- 需要把spring-boot-starter-actuator依赖去掉,否则configclient无法连接到配置中心 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
</dependencies>
然后修改webhook 刷新配置url 的接口为monitor接口:
重启configserver,修改git上的 order-service.yml以及 user-service.properties 中的配置项:
请求http://localhost:8081/user/config ,可以看到配置项自己刷新了
这样就通过springcloudbus 消息总线实现了所有configclient上的配置的动态刷新!
代码地址