工具:idea
详细了解博客连接:https://blog.csdn.net/weixin_43591980/article/details/106255122
视频链接:https://www.bilibili.com/video/BV1jJ411S7xr
概述
分布式系统面临的—配置文件的问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务,由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。SpringCloud提供了ConfigServer来解决这个问题,我们每一个微服务自己带着一个application.yml,那上百的配置文件要修改起来,岂不是要疯。
什么是SpringCloud config分布式配置中心
SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置。
SpringCloud Config分为服务端和客户端两部分;
服务端也称为 分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。
客户端则是通过制定的配置中心来管理应用资源以及与业务相关的配置内容, 并在启动的时候从配置中心获取和加载配置信息,配置服务器默认采用git来存储配置信息,这样有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
SpringCloud Config分布式配置中心能干什么
- 集中管理配置文件
- 不同环境,不同配置,动态化的配置更新,分环境部署,比如/dev /test/ /prod /beta /release通过—三个横杠隔开
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
- 当配置发生变动是,服务不需要重启即可感知到配置的变化,并应用新的配置。这个得需要热部署插件才可以做到。
- 将配置信息以REST借口的形式暴露
SpringCloud Config分布式配置中心与GitHub整合
由于SpringCloud Config默认使用Git来存储配置文件(也有其他方式,比如支持SVN和本地文件),但是最推荐的还是Git,而且使用的是http/https访问的形式;
Git环境搭建
首先得安装Git,安装完毕后,电脑右键会出现两个git的新建项
搜索码云,注册或者登陆账号,然后创建一个仓库
点击创建后页面跳转填写信息
完成后会看到这样的一个界面
点击克隆/下载按钮,选择ssh,点击复制
在电脑上随便找个位置新建一个文件夹,名称随便取,然后电脑右键打开git bash
回车
上面说没有权限公开,在gitee刚刚创建仓库的界面上点击git大全
往下翻,找到配置
输入命令查看配置:git config –list
没有用户配置
配置用户信息
# 设置提交代码时的用户信息
$ git config [--global] user.name "[name]"
$ git config [--global] user.email "[email address]"
再次输入git config –list
生成秘钥。首先找到.ssh文件,然后删掉
在你新建放置springcloud-config仓库的文件夹里面右键打开git bash。
输入这个命令来生成秘钥ssh-keygen -t rsa -C “847475198@qq.com”
。当然,QQ号就写成自己的即可。
回到.ssh文件那边看,可以看到生成了两个文件
需要添加秘钥到GitHub上面,上图的第二个文件打开,复制
复制到公钥栏里面,输入密码验证
打开个人主页,选择新建的仓库名称,再次复制地址进行克隆。打开当前要放置的项目—》右键—》git bash
可以打开看到,跟gitee上面的一模一样
在这个目录下新建一个application.yml文件,在里面进行编辑
把application.yml提交到Gitee码云上
1、把application.yml添加到暂存区。git add .
2、提交到本地git commit -m “”
3、push到远程
刷新gitee,可以看到已经上传成功
服务端配置gitee配置
目录结构
新建一个module,**
**,后面的端口号可以自已定义。
Pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
</dependencies>
Application.yml文件
server:
port: 6666
spring:
application:
name: springcloud-config-server
#连接远程仓库
cloud:
config:
server:
git:
uri: https://gitee.com/angelordevil/springcloud-config.git #连接gitee上的HTTPS的路径
也就是这个HTTPS远程地址。点击复制
Config_Server_6666 启动类
package com.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
@SpringBootApplication
@EnableConfigServer
public class Config_Server_6666 {
public static void main(String[] args) {
SpringApplication.run(Config_Server_6666.class,args);
}
}
然后启动,输入地址http://localhost:6666
如果启动失败,就去pom文件中把eureka依赖删除,目前暂时不用这个功能。不然读取的时候会一直失败然后一直去读取。接着添加一个actuator监控依赖
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
访问成功后
想访问谁就在地址栏上写上谁,比如访问application.yml文件。就输入地址: http://localhost:6666/application-dev.yml
这个可以通过java程序去读取到GitHub的所有东西
官方文档中介绍HTTP服务具有一下格式资源。也就是可以通过下面这些路径方式去加载资源
/{application}/{profile}[/{label}] //http://localhost:6666/application/dev/master
意思:读取git上的master分支上的application配置中的dev属性
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
客户端连接服务端访问远程
首先在项目路径下新建一个config-client.yml文件,然后打开编辑,写上配置
右键打开git bash
Push到gitee上
可以到gitee上查看
新建一个module,springcloud-config-client-7777
目录结构
Pom文件
<dependencies>
<!--config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
Bootstrap.yml。bootstrap.yml是系统级别的配置,而application.yml是用户级别的配置。所以bootstrap.yml的优先级高
# 系统级别的配置
#客户端连接远程项目。先去连接6666中的服务,再通过6666这个服务去连接GitHub上的获取
spring:
cloud:
config:
name: config-client #需要从git上获取的资源名称,无需后缀
profile: dev
label: master
uri: http://localhost:6666
Application.yml
# 用户级别的配置
spring:
application:
name: springcloud-config-client-7777
ConfigClient_7777
package com.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//客户端去拿服务端的东西
@SpringBootApplication
public class ConfigClient_7777 {
public static void main(String[] args) {
SpringApplication.run(ConfigClient_7777.class,args);
}
}
ConfigClientController
package com.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConfigClientController {
/*参照gitee上的config-client.yml文件注入进去*/
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-url.defualtZone}")
private String eurekaServer;
@Value("${server.port}")
private String port;
//如果能打印出来这段话证明成功
@RequestMapping("/config")
public String getConfig(){
return "applicationName:" + applicationName+
"eurekaServer:"+ eurekaServer+
"port:" + port;
}
}
保证远程是能连接上的
启动7777这个服务,因为没有配置端口号,默认走的是8201这个分支。输入http://localhost:8201/
然后输入http://localhost:8201/config
然后改bootstrap.yml文件
再访问就只能访问8202这个分支了。
总结:
可以写上多个客户端,把配置统一放在GitHub上,通过server去连接GitHub。有问题可以在GitHub去调节,然后代码还是代码,server还是server,远程的变化对于这两个没有影响。
远程配置实战测试
新建两个application.yml
config-eureka.yml
spring:
profiles:
active: dev #激活dev
#---
server:
port: 7001
#spring配置
spring:
profiles: dev
application:
name: springcloud-config-eureka
# eureka配置
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false # 表示是否向eureka注册中心注册自己
fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
service-url:
# 单机
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #监控页面
# 集群(关联)在7001中挂载7002
defultZone: http://eureka7002.com:7002/eureka/,http://eureka7003:com:7003/eureka/
#----
server:
port: 7001
#spring配置
spring:
profiles: test
application:
name: springcloud-config-eureka
# eureka配置
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false # 表示是否向eureka注册中心注册自己
fetch-registry: false #fetch-registry如果为false,则表示自己为注册中心
service-url:
# 单机
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #监控页面
# 集群(关联)在7001中挂载7002
defultZone: http://eureka7002.com:7002/eureka/,http://eureka7003:com:7003/eureka/
application.yml
spring:
profiles:
active: dev #激活dev
#----
server:
port: 8001
#mybatis配置
mybatis:
type-aliases-package: com.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml #mybatis的核心配置
mapper-locations: classpath:mybatis/mapper/*.xml
#spring配置
spring:
profiles: dev
application:
name: springcloud-config-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver #org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/cloud01?useUnicode=true&characterEncoding=utf-8
username: root
password: sa123
#eureka的配置,defualtZone 服务注册到7001中的yml的路径上
eureka:
client:
service-url:
defualtZone: http://eureka7001.com :7001/eureka/,http://eureka7002.com :7002/eureka/,http://eureka7003.com :7003/eureka/ #http://localhost:7001/eureka/
instance:
instance-id: spring-cloud-provider-dept8001 #修改eureka上的默认描述信息
# prefer-ip-address: true #可以显示服务ip地址,可以定位到远程的IP地址
#info配置
info:
app.name: study-springcloud
company.name: gd.familychen.com
#----
server:
port: 8001
#mybatis配置
mybatis:
type-aliases-package: com.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml #mybatis的核心配置
mapper-locations: classpath:mybatis/mapper/*.xml
#spring配置
spring:
profiles: dev
application:
name: springcloud-config-dept
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver #org.gjt.mm.mysql.Driver
url: jdbc:mysql://localhost:3306/cloud02?useUnicode=true&characterEncoding=utf-8
username: root
password: sa123
#eureka的配置,defualtZone 服务注册到7001中的yml的路径上
eureka:
client:
service-url:
defualtZone: http://eureka7001.com :7001/eureka/,http://eureka7002.com :7002/eureka/,http://eureka7003.com :7003/eureka/ #http://localhost:7001/eureka/
instance:
instance-id: spring-cloud-provider-dept8001 #修改eureka上的默认描述信息
# prefer-ip-address: true #可以显示服务ip地址,可以定位到远程的IP地址
#info配置
info:
app.name: study-springcloud
company.name: gd.familychen.com
然后push到远程。跟上面一样的操作
- git add .
- git status
- git commit -m “这里填第几次提交的信息”
- git push origin master
新建一个module,springcloud-config-eureka-7001。把7001的内容复制过来改。
目录结构:
Pom文件:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
</dependencies>
ConfigEurekaServer_7001
package com.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer//开启eureka服务 EnableEurekaServer服务端的启动类,可以接受别人注册进来
public class ConfigEurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(ConfigEurekaServer_7001.class,args);
}
}
bootstrap.yml
spring:
cloud:
config:
name: config-eureka
label: master
profile: dev
uri: http://localhost:6666
application.yml
#配置信息,代表是哪个(客户端)module的配置
spring:
application:
name: springcloud-config-eureka-7001
启动6666,让它连接远程的config-eureka的dev,访问路径:localhost:6666/master/config-eureka-dev.yml
。测试成功后,启动springcloud-config-eureka-7001,访问路径:localhost:7001
新建一个module,springcloud-config-dept-8001,复制8001修改一下配置。
目录结构:
Pom文件
<dependencies>
<!--要拿实体类,所以要配置api module-->
<dependency>
<groupId>com.cloud</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!--数据库-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--druid数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--logback-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--jetty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--eureka依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--actuator 完善监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--hystrix依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
<!--config-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.2.7.RELEASE</version>
</dependency>
</dependencies>
DeptController
package springcloud.controller;
import com.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import springcloud.service.DeptService;
import java.util.List;
//提供restful服务
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
//获取一些配置的信息,得到具体的微服务
@Autowired
private DiscoveryClient client;
@PostMapping("/dept/add")
public boolean addDept(Dept dept){
return deptService.addDept(dept);
}
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id){
Dept dept = deptService.queryById(id);
if (dept==null){
throw new RuntimeException("not find resource");
}
return dept;
}
@GetMapping("/dept/list")
public List<Dept> queryAll(){
return deptService.queryAll();
}
//注册进来的微服务,获取一些消息
@GetMapping("/dept/discovery")
public Object discovery(){
//获取微服务列表的清单
List<String> services = client.getServices();
System.out.println("discovery=>services:"+services);
//得到一个具体的微服务信息,通过具体的微服务id,applicationName:
List<ServiceInstance> instances = client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
for (ServiceInstance instance: instances) {
System.out.println(
instance.getHost()+"\t"+
instance.getPort()+"\t"+
instance.getUri()+"\t"+
instance.getInstanceId()
);
}
return this.client;
}
}
DeptDao
package springcloud.dao;
import com.springcloud.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface DeptDao {
//增加
public boolean addDept(Dept dept);
//查询
public Dept queryById(Long id);
//查询所有
public List<Dept> queryAll();
}
DeptService
package springcloud.service;
import com.springcloud.pojo.Dept;
import java.util.List;
public interface DeptService {
//增加
public boolean addDept(Dept dept);
//查询
public Dept queryById(Long id);
//查询所有
public List<Dept> queryAll();
}
DeptServiceImp
package springcloud.service;
import com.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import springcloud.dao.DeptDao;
import java.util.List;
@Service
public class DeptServiceImp implements DeptService {
@Autowired
private DeptDao deptDao;
@Override
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
@Override
public Dept queryById(Long id) {
return deptDao.queryById(id);
}
@Override
public List<Dept> queryAll() {
return deptDao.queryAll();
}
}
DeptProvider_8001
package springcloud;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
//启动类
@SpringBootApplication
@EnableEurekaClient //开启注解,在服务启动后自动配置到7001中的EurekaServer_7001去
@EnableDiscoveryClient //服务发现
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
//添加一个servlet
//固定的代码
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");//访问这个页面就可以被监控了
return registrationBean;
}
}
application.yml
spring:
application:
name: springcloud-config-dept-8001
bootstrap.yml
spring:
cloud:
config:
name: config-dept
label: master
profile: dev
uri: http://localhost:6666
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
DeptMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.DeptDao">
<insert id="addDept" parameterType="Dept">
insert into dept(dname,db_source)
values (#{dname},DATABASE())
</insert>
<select id="queryById" resultType="Dept" parameterType="Long">
select * from dept where deptno = #{deptno};
</select>
<select id="queryAll" resultType="Dept">
select * from dept;
</select>
</mapper>
最主要是改配置,代码不需要动。
启动springcloud-config-dept-8001,能放到eureka注册中心证明成功。访问路径:localhost:8001/dept/get/1。http://localhost:6666/master/config-dept-dev.yml
假设在gitee上改一些配置信息,改config-dept.yml文件,下面那个spring配置改成test。然后在最上面把数据库cloud01改成cloud03,如果查询数据的话就会走cloud03这个数据库的数据
提交信息
远程改了信息,在项目中热部署一下,这样才能更改信息。访问地址:localhost:8001/dept/get/1
这个可以看到数据库变成了cloud03了。然后可以自行把所有项目中的所有配置都丢到远程上。