SpringCloud之服务配置
1.config
1.1定义
对于分布式微服务,有很多的配置,那么修改起来很麻烦。这就需要对这些配置文件进行集中式的管理,config的功能就是用来统一管理配置文件的。
它为微服务提供集中化的外部配置支持,配置服务器为各个不同的微服务的所有环境提供了中心化的外部配置。它也分为服务端和客户端。
1.2项目开发
源代码:https://github.com/zhongyushi-git/cloud-config.git
1.2.1服务端配置
1)在github上创建服务配置的仓库spring-cloud-server-config
2)把仓库克隆到本地
git clone https://github.com/zhongyushi-git/spring-cloud-server-config.git
3)在spring-cloud-server-config目录下创建配置文件application.yml
注意,配置文件必须以utf-8编码保存。
#指定激活哪个配置
spring:
profiles:
active: dev #开发环境配置
---
spring:
profiles: dev
application:
name: cloud-config-dev #参测试环境配置
---
spring:
profiles: test
application:
name: cloud-config-test
4)把创建的yml推送到github上
git add .
git commit -m 'first commit'
git push
5)创建父模块cloud-config,创建子模块cloud-config-server3344
<?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.zys.cloud</groupId>
<artifactId>cloud-config</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>cloud-config-server3344</module>
</modules> <!--统一管理jar包版本-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<lombok.version>1.16.18</lombok.version>
<log4j.version>1.2.17</log4j.version>
<mysql.version>5.1.47</mysql.version>
<druid.version>1.1.16</druid.version>
<mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties> <!-- 依赖管理,父工程锁定版本-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud alibaba 2.1.0-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build> </project>
父模块pom
6)子模块3344导入依赖
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--config-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency> </dependencies>
7)yml配置
server:
port: 3344 spring:
application:
name: cloud-config-server
cloud:
config:
server:
git:
#github仓库上面的git仓库名字
uri: https://github.com/zhongyushi-git/spring-cloud-server-config.git
8)在com.zys.cloud包下创建启动类
package com.zys.cloud; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer; @SpringBootApplication
@EnableConfigServer
public class ConfigServerMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigServerMain3344.class, args);
}
}
9)hosts添加映射
127.0.0.1 config-3344.com
10)启动测试
配置读取规则
/{application}/{profile}[/{label}]
/{label}/{application}-{profile}.yml
/{application}-{profile}.yml
启动3344,在浏览器分别输入
http://config-3344.com:3344/application/dev/master
http://config-3344.com:3344/application-dev.yml
http://config-3344.com:3344/master/application.dev.yml
都可以看到相关的配置信息,此时已完成从github上读取配置信息。
1.2.2客户端配置
1)在spring-cloud-server-config目录下创建配置文件cloud-config-client.yml
注意,配置文件必须以utf-8编码保存。
spring:
profiles:
active: dev ---
server:
port: 8021 spring:
profiles: dev
application:
name: cloud-config-client ---
server:
port: 8022 spring:
profiles: test
application:
name: cloud-config-client
2)把创建的yml推送到github上
3)创建模块cloud-config-client3355
此模块用于连接config服务测试。
4)pom导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--config客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
5)yml配置
bootstrap.yml:系统级别的配置,优先级更高
application.yml:用户级别的配置
spring:
cloud:
config:
#指定从github读取的配置文件的名称,不加后缀名
name: cloud-config-client
#指定访问的配置环境
profile: dev
label: master
uri: http://config-3344.com:3344
bootstrap.yml
spring:
application:
name: cloud-config-client
application.yml
6)在com.zys.cloud包下创建启动类
package com.zys.cloud; import javafx.application.Application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class ConfigClientMain3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3355.class, args);
}
}
7)在com.zys.cloud包下创建测试接口ConfigClientTest
package com.zys.cloud; import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; @RestController
public class ConfigClientTest { @Value("${spring.application.name}")
private String applicationName; @Value("${server.port}")
private String serverPort; @GetMapping("/config")
public String test(){
String str="applicationName: "+applicationName+"\t"+"serverPort:"+serverPort;
return str;
} }
8)hosts添加映射
127.0.0.1 config-client.com
9)启动测试
先启动3344,然后3355启动。访问http://config-client.com:8021/config可以看到相关的返回信息。
1.2.3动态刷新配置
动态刷新是说,当我们修改了spring-cloud-server-config目录下的配置文件时,项目会动态的刷新配置。但是会出现一个问题,就是只要修改了配置文件,还要重启3355才能使用最新的配置。这样会重复的启动服务,比较麻烦,有一种不重启服务的方法就是手动的刷新配置。
1)在3355中添加一个访问接口,用于访问配置的信息
@Value("${config.info}")
private String info; @GetMapping("/config2")
public String test2(){
String str="info: "+info;
return str;
}
2)修改spring-cloud-server-config目录下配置文件cloud-config-client.yml
config:
info: version1
3)把这个文件推送到github上,然后启动3344,最后3355启动。访问http://config-client.com:8021/config2,此时会看到返回的信息是info: version1。
4)再修改spring-cloud-server-config目录下配置文件cloud-config-client.yml,把version1改为version2,然后推送到github。不重启3355。访问http://config-client.com:8021/config2,返回的信息还是info: version1。
5)使用postman发送一条post请求给服务3355
http://localhost:8021/actuator/refresh
发送请求的原因就是通知3355服务,去拉取最新的配置。需要注意的是,这里3355使用的端口是根据配置文件来的,是8021。
6)再访问http://config-client.com:8021/config2,返回的信息就为info: version2。
从这里可以看出,并没有重启服务,只是手动发送了一条请求,就实现了动态的刷新。
1.2.4项目实战
在1.2.2中,配置服务端只是一个测试的demo,并没有结合项目,在实际开发中不需要此模块。这一小节就简单的结合项目进行统一配置。
(1)配置版eureka服务
1)创建子模块cloud-config-eureka-server7001
2)pom导入
<dependencies>
<!--eureka server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--boot web actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--config客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency> </dependencies>
3)yml配置
bootstrap.yml主要指定github上面的配置文件名称,而application.yml指定应用的名称,两者必不可少。
spring:
cloud:
config:
#指定从github读取的配置文件的名称,不加后缀名
name: cloud-config-eureka-client
#指定访问的配置环境
profile: dev
label: master
uri: http://config-3344.com:3344
bootstrap.yml
spring:
application:
name: cloud-config-eureka-client
application.yml
4)在com.zys.cloud包下创建启动类
package com.zys.cloud; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication
@EnableEurekaServer
public class ConfigEurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(ConfigEurekaMain7001.class, args);
}
}
5)在pring-cloud-server-config目录下创建配置文件cloud-config-eureka-client.yml
spring:
profiles:
active: dev ---
server:
port: 7001 spring:
profiles: dev
application:
name: cloud-config-eureka-client eureka:
instance:
#eureka服务端的实例名称
hostname: localhost
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ ---
server:
port: 7002 spring:
profiles: test
application:
name: cloud-config-eureka-client eureka:
instance:
#eureka服务端的实例名称
hostname: localhost
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
此文件是eureka的配置,由原来在项目中的配置到现在提出来放到github上配置。创建完成后提交到github。
6)运行测试
启动3344,然后再启动eureka7001,浏览器输入http://127.0.0.1:7001/可以正常访问eureka页面。
(2)配置版服务提供者
1)创建子模块cloud-config-provider8001
2)pom导入
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--引入自己定义的模块-->
<dependency>
<groupId>com.zys.cloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--mysql-connector-java-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--config客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
3)yml配置
spring:
cloud:
config:
#指定从github读取的配置文件的名称,不加后缀名
name: cloud-config-provider-client
#指定访问的配置环境
profile: dev
label: master
uri: http://config-3344.com:3344
bootstrap.yml
spring:
application:
name: cloud-config-provider-client
application.yml
bootstrap.yml主要指定github上面的配置文件名称,而application.yml指定应用的名称,两者必不可少。
4)创建接口和相关的类,见源码
5)在pring-cloud-server-config目录下创建配置文件cloud-config-provider-client.yml
spring:
profiles:
active: dev ---
server:
port: 8001 spring:
profiles: dev
application:
name: cloud-config-provider-client
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2020?useUnicode=true&characterEncoding-utr-8&useSSL=false
username: root
password: 123456 mybatis:
mapper-locations: classpath:mapper/*.xml
#所有Entity别名类所在包
type-aliases-package: com.zys.cloud.entity #把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka/
#设置入驻的服务的名称,是唯一的
instance:
instance-id: cloud-config-provider8001
#访问路径显示ip
prefer-ip-address: true ---
server:
port: 8001 spring:
profiles: test
application:
name: cloud-config-provider-client
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: org.gjt.mm.mysql.Driver #mysql驱动包
url: jdbc:mysql://localhost:3306/db2021?useUnicode=true&characterEncoding-utr-8&useSSL=false
username: root
password: 123456 mybatis:
mapper-locations: classpath:mapper/*.xml
#所有Entity别名类所在包
type-aliases-package: com.zys.cloud.entity #把客户端注册到服务列表中
eureka:
client:
#表示是否将自己注册进EurekaServer默认为true
register-with-eureka: true
#是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetch-registry: true
service-url:
defaultZone: http://localhost:7002/eureka/
#设置入驻的服务的名称,是唯一的
instance:
instance-id: cloud-config-provider8001
#访问路径显示ip
prefer-ip-address: true
此文件是服务提供者8001的配置,由原来在项目中的配置到现在提出来放到github上配置。创建完成后提交到github。
6)运行测试
启动3344,然后再启动eureka7001,最后启动8001,浏览器输入http://localhost:8001/user/get/1可以正常访问数据。
从这里可以看出,在项目中的yml并没有具体的配置。把配置进行统一的管理,如果需要修改配置文件,只需要把github上的配置项目拉取下来修改后再提交即可。
2.bus(消息总线)
2.1定义
对于上面config的项目,我们只能通过手动的方式进行动态刷新配置,而如果同时修改了多个配置文件,那么就要进行多次的手动刷新,而bus可以实现一次刷新,在其他的服务中不需要再刷新就可生效。也就是说,它是一个把分布式分摊的节点与轻量级消息系统链接起来的框架,整合了java的事件处理机制和消息中间件的功能,目前仅支持RabbitMQ和Kafka。它能管理和传播分布式系统间的消息,可用于广播状态更改、事件推送等。
基本原理:ConfigClient实例都监听MQ中同一个topic。当一个服务刷新数据时,就会把这个信息放入topic中,这样其他监听同一topic的服务就能得到通知,然后去更新各自的配置。
设计思想:利用消息总线触发一个服务端ConfigServer的/bus/refresh端点从而来刷新客户端的配置。
2.2项目开发
本项目在config项目的基础上进行开发。
(1)环境配置
在使用bus之前,必须先安装erlang和RabbitMQ。erlang的安装和RabbitMQ的安装请参考https://www.cnblogs.com/zys2019/p/12828152.html。
(2)3344服务添加消息总线支持
1)添加依赖
<!--添加消息总线RbbitMQ支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2)yml配置
(3)3355服务添加消息总线支持
1)添加依赖
<!--添加消息总线RbbitMQ支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
2)bootstrap.yml配置
spring:
cloud:
config:
#指定从github读取的配置文件的名称,不加后缀名
name: cloud-config-client
#指定访问的配置环境
profile: dev
label: master
uri: http://config-3344.com:3344
#rabbit相关配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest #rabbitmq相关配置,暴露端点
management:
endpoints:
web:
exposure:
include: '*'
(4)启动测试
1)先启动3344,然后启动3355。访问http://config-client.com:8021/config2,此时会看到返回的信息是info: version2。
2)再修改spring-cloud-server-config目录下配置文件cloud-config-client.yml,把version2改为version3,然后推送到github。不重启3355。访问http://config-client.com:8021/config2,返回的信息还是info: version2。
3)使用postman发送一条post请求给服务3344去刷新配置中心服务
http://localhost:3344/actuator/bus-refresh
4)再访问http://config-client.com:8021/config2,返回的信息就为info: version3。这里并没有给3355服务发送post请求,也实现了动态的刷新,这就是bus的广播。如果想验证bus的广播,可以再新建一个3366的client,配置同3355,只是端口号不一样,然后可以实现同样的效果。
最新文章
- Win10上使用SVN遇到的一些问题
- Python模块常用的几种安装方式
- NOI模拟赛Day4
- Robots on a grid(DP+bfs())
- (转)Redis 集群方案
- 【转载】B树、B-树、B+树、B*树都是什么
- MySql中的事务嵌套
- python calendar标准库基础学习
- BackgroundWorker用法
- delphi json(CDS包含了Delta数据包)
- 理解php的opcode
- MongoDB基础教程系列--第六篇 MongoDB 索引
- SyntaxError: Missing parentheses in call to 'print'
- Oracle 中Return 和exit的区别
- pdfmake导出页眉页脚问题
- PropertyChangeSupport 监听器模式的应用
- 使用cmake编译luabind
- 【BZOJ】3168: [Heoi2013]钙铁锌硒维生素
- python分享题目
- MySQL数据源驱动报错
热门文章
- 小白搭建WNMP详细教程---NGINX、MYSQL、PHP的整合配置
- TcaplusDB 10周年 风雨兼程破浪行 自研存储见成长
- HDU4358 Boring counting【dsu on tree】
- BZOJ3238 [Ahoi2013]差异 【SAM or SA】
- 2019牛客多校 Round8
- Traveling Salesman among Aerial Cities 旅行商(TSP)问题
- poj 1511-- Invitation Cards (dijkstra+优先队列)
- 【noi 2.6_8471】切割回文(DP)
- Codeforces Educational Rounds 85 A~C
- redis如何实现高可用【主从复制、哨兵机制】