SpringCloud微服务(二):配置中心

编程

pring Cloud Config为分布式系统中的外部化配置提供服务器和客户端支持。

Spring Cloud Config原理

创建Spring Cloud 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>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.2.2.RELEASE</version>

<relativePath/>

</parent>

<groupId>proj.ms</groupId>

<artifactId>config</artifactId>

<version>1.0.0-SNAPSHOT</version>

<name>config</name>

<description>config center</description>

<properties>

<java.version>1.8</java.version>

<spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-config-monitor</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-bus-amqp</artifactId>

</dependency>

<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>

<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>

<scope>test</scope>

<exclusions>

<exclusion>

<groupId>org.junit.vintage</groupId>

<artifactId>junit-vintage-engine</artifactId>

</exclusion>

</exclusions>

</dependency>

</dependencies>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>${spring-cloud.version}</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

配置说明

  • spring.cloud.config.server.git 使用Git对配置文件进行管理。uri指定Git仓库地址。
  • spring.rabbitmq 使用rabbitmq作为消息队列,用于配置的自动刷新。

添加注解

在启动类上添加@SpringBootApplication、@EnableDiscoveryClient、@EnableConfigServer三个注解:

@SpringBootApplication

@EnableDiscoveryClient

@EnableConfigServer

@ServletComponentScan

public class ConfigApplication {

public static void main(String[] args) {

SpringApplication.run(ConfigApplication.class, args);

}

}

说明

  • @EnableDiscoveryClient 将Spring Cloud Config 服务端作为Eureka的客户端。Spring Cloud Config作为微服务在Eureka中注册,其它服务可通过服务名直接访问配置中心。
  • @EnableConfigServer 标识此应用为ConfigServer,启用默认配置。
  • @ServletComponentScan 扫描Servlet组件,将自定义过滤器添加至Spring中。

添加配置

spring:

application:

name: config

cloud:

config:

server:

git:

uri: "http://gitlab.figring.com/ms/config.git"

username: "config-center"

password: "W&Yd)R3Vf"

rabbitmq:

host: 192.168.75.130

port: 5672

username: guest

password: guest

eureka:

client:

service-url:

defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/

fetch-registry: true

registry-fetch-interval-seconds: 8

instance:

lease-renewal-interval-in-seconds: 4

lease-expiration-duration-in-seconds: 12

server:

port: 8888

management:

endpoints:

web:

exposure:

include: "*"

配置说明

  • spring.cloud.config.server.git 使用Git对配置文件进行管理。uri指定Git仓库地址。
  • spring.rabbitmq 使用rabbitmq作为消息队列,用于配置的自动刷新。

添加GitLab的Web Hook

在GitLab中添加Spring Cloud Config 服务端配置刷新的回调地址。上述配置文件中配置的GitLab仓库若发生push event,GitLab将调用此地址通知配置中心。配置中心暴露的端点为/actuator/bus-refresh,对应源码中的RefreshBusEndpoint类。

修改GitLab的Web Hook的Request Body

GitLab调用/actuator/bus-refresh端点,在配置中心会发生Json序列化异常。通过拦截bus-refresh端点并进行自定义修改Request Body以达到正常调用的目的。

/**

* 用于拦截bus-refresh端点的请求

*/

@WebFilter(filterName = "BusRefreshFilter", urlPatterns = "/*")

public class BusRefreshFilter implements Filter {

public static final String BUS_REFRESH_ENDPOINT = "/bus-refresh";

@Override

public void init(FilterConfig filterConfig) {

}

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,

FilterChain filterChain)

throws IOException, ServletException {

HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;

String url = httpServletRequest.getRequestURI();

// 只过滤/bus-refresh端点

if (!url.endsWith(BUS_REFRESH_ENDPOINT)) {

filterChain.doFilter(servletRequest, servletResponse);

return;

}

//修改Request Body

CustometRequestWrapper requestWrapper = new CustometRequestWrapper(httpServletRequest);

filterChain.doFilter(requestWrapper, servletResponse);

}

@Override

public void destroy() {

}

}

/**

* Request包装类

*/

public class CustometRequestWrapper extends HttpServletRequestWrapper {

public CustometRequestWrapper(HttpServletRequest request) {

super(request);

}

@Override

public ServletInputStream getInputStream() {

byte[] bytes = new byte[0];

ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);

return new ServletInputStream() {

@Override

public boolean isFinished() {

return byteArrayInputStream.read() == -1;

}

@Override

public boolean isReady() {

return false;

}

@Override

public void setReadListener(ReadListener readListener) {

}

@Override

public int read() {

return byteArrayInputStream.read();

}

};

}

}

启动Spring Cloud Config 服务端

启用应用程序。

客户端应用

添加客户端配置文件

在Git仓库中创建user-service-dev.ym文件,添加以下内容:

student:

name: student3

age: 555

spring:

rabbitmq:

host: 192.168.75.130

port: 5672

username: guest

password: guest

客户端依赖

<?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>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.1.2.RELEASE</version>

<relativePath/>

</parent>

<groupId>proj.ms</groupId>

<artifactId>user-center</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>user-center</name>

<description>user center</description>

<properties>

<java.version>1.8</java.version>

<spring-cloud.version>Greenwich.SR2</spring-cloud.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</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-starter-bus-amqp</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-actuator</artifactId>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</dependency>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-test</artifactId>

<scope>test</scope>

<exclusions>

<exclusion>

<groupId>org.junit.vintage</groupId>

<artifactId>junit-vintage-engine</artifactId>

</exclusion>

</exclusions>

</dependency>

</dependencies>

<dependencyManagement>

<dependencies>

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-dependencies</artifactId>

<version>${spring-cloud.version}</version>

<type>pom</type>

<scope>import</scope>

</dependency>

</dependencies>

</dependencyManagement>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

  • 注:客户端需引入spring-cloud-starter-bus-amqp依赖,以便在配置发生变更的时候,通过消息队列获取配置消息。

添加注解

@SpringBootApplication

@EnableDiscoveryClient

public class UserCenterApplication {

public static void main(String[] args) {

SpringApplication.run(UserCenterApplication.class, args);

}

}

添加配置

在resources目录中创建boostrap.yml文件,添加以下内容:

spring:

application:

name: user-service

cloud:

config:

discovery:

enabled: true

service-id: config

profile: dev

eureka:

client:

service-url:

defaultZone: http://peer1:8761/eureka/,http://peer2:8762/eureka/,http://peer3:8763/eureka/

server:

port: 18080

management:

endpoints:

web:

exposure:

include: "*"

  • spring.cloud.config.discovery 中service-id指定配置将从名为config的微服务获取。

功能验证

启动user-service微服务,并修改Git仓库中的配置。观察消息队列、配置中心与user-service微服务日志消息队列日志是否正常。
RabbitMQ中消息存在消息生布的消费:

客户端日志,客户端已经重新从配置中心获取的新的配置:

2019-12-24 15:56:32.598  INFO 15408 --- [xuKlDf_RcOW8Q-1] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at : http://localhost:8888/

2019-12-24 15:56:34.263 INFO 15408 --- [xuKlDf_RcOW8Q-1] c.c.c.ConfigServicePropertySourceLocator : Located environment: name=user-service, profiles=[dev], label=null, version=7ea75c74cc03d422b00403a2b6fbc920ce487d87, state=null

2019-12-24 15:56:34.264 INFO 15408 --- [xuKlDf_RcOW8Q-1] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name="configService", propertySources=[MapPropertySource {name="configClient"}, MapPropertySource {name="http://gitlab.figring.com/ms/config.git/user-service-dev.yml"}]}

配置动态刷新测试:

@RestController

@RefreshScope

public class UserController {

@Value("${student.name}")

private String name;

@GetMapping("name")

public String getName() {

return name;

}

}

动态修改配置,访问http://localhost:18080/name ,查看配置是否动态变化。

Spring Cloud Config高可用方案

架构图


Spring Cloud Config Server成为一个普通的微服务,在负载均衡组件的作用下为其它业务相关的微服务提供配置服务。

问题汇总

GitLab调用/actuator/bus-refresh端点时发生Json异常

原因及解决方案见上文。

 

以上是 SpringCloud微服务(二):配置中心 的全部内容, 来源链接: utcz.com/z/512002.html

回到顶部