前沿:参考文章,非常建议食用
配置中心(Config)使用详解
配置中心(Config)和消息总线(Bus)完美使用版
上面的两篇文章里面都是config-server向eureka注册,其它服务根据config-server在eureka中的名称获取微服务实例后再获取对应自身的配置文件,这样确实可以完成,但是有一个问题,因为这样config-server需要依赖eureka,即eureka必须先跑起来(即eureka的配置文件必须在本地),这样一来如果eureka也想把配置文件放在github上,他们就会冲突,另一种方法是如果向我后面这样(章节四)直接指定ip和端口,虽然可以解决问题,将eureka的配置文件也放在远端,可是,这样一来,eureka无法获取config-server搭建的集群,两种方式如下(第一至三节为第一种,第四节为第二种)
模块说明:
模块名称 | 说明 |
---|---|
eureka | 服务的注册中心 |
config-server | springCloud-config的服务中心 |
stock | 库存模块 |
user | 用户模块 |
步骤如下:
直接建立一个eureka模块即可,和以往的springcloud模块建立一模一样,
这里eureka的配置文件采用本地的方式(关于把eureka的配置文件也放在git服务器上,请看文章第四节),这里就不再啰嗦了
因为是springcloud-config的服务端,所以我们需要config的server依赖
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
dependency>
dependencies>
需要开启@EnableConfigServer
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class,args);
}
}
配置文件如下
spring.application.name=config-server
server.port=9005
eureka.client.serviceUrl.defaultZone= http://localhost:8005/eureka/
eureka.instance.prefer-ip-address = true
spring.cloud.config.server.git.uri = https://github.com/wandun/config-repo
spring.cloud.config.server.git.search-paths = /userModuleConfig,/stockModuleConfig
spring.cloud.config.server.git.username = github的用户名
spring.cloud.config.server.git.password = github的密码
spring.cloud.config.server.git.skip-ssl-validation=true
说明:
- spring.application.name: 这个是指定该模块在eureka中的服务名称。
- server.port:服务指定的端口。
- eureka.client.serviceUrl.defaultZone: 这个是设置与Eureka Server交互的地址,客户端的查询服务和注册服务都需要依赖这个地址。
- spring.cloud.config.server.git.uri: 配置的Git仓库的地址,我这里是专门建立了一个github的仓库
- spring.cloud.config.server.git.search-paths: git仓库地址下的相对地址 多个用逗号","分割。
- spring.cloud.config.server.git.username:git仓库的账号。
- spring.cloud.config.server.git.password:git仓库的密码。
对应上面的 search-paths = /userModuleConfig,/stockModuleConfig,一个目录对应一个模块的配置文件,每一个模块又都有dev,uat,pro三种配置环境
server.port=8088 # (stock 模块的启动端口)
current.profile=dev # 根据当前的配置文件(uat ,dev, pro)
server.port=8089 # (user模块的启动端口)
current.profile=dev # 根据当前的配置文件(uat ,dev, pro)
后面因为需要通过浏览器访问,所以需要web依赖,而且因为stock是springcloud-config的客户端,所以我们需要config的client依赖,并且我们需要向eureka注册,所以我们需要eureka的客户端
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
dependencies>
@SpringBootApplication
@EnableDiscoveryClient
public class UserApplication {
public static void main(String[] args) {
SpringApplication.run(UserApplication.class,args);
}
}
这个模块的配置文件名称一定一定要是bootstrap开头,不能是application,因为stock模块的配置文件不是读取本地的application.properties,而是需要去获取远端的,所以我们使用bootstrap的 优先级会更高,在加载application之前包配置从远端读取到手后就可以了!
spring.cloud.config.name=stockconfig
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
eureka.client.serviceUrl.defaultZone=http://localhost:8005/eureka/
eureka.instance.prefer-ip-address = true
说明:
- spring.cloud.config.name: 获取配置文件的名称的前缀,请详细查看前面仓库说明截图
- spring.cloud.config.profile: 获取配置的策略,dev,uat,pro
- spring.cloud.config.label:获取配置文件的分支,默认是master。如果是- 是本地获取的话,则无用。
-spring.cloud.config.discovery.enabled: 开启配置信息发现。- spring.cloud.config.discovery.serviceId: 指定配置中心(config-server)在eureka中的service-id
- eureka.client.serviceUrl.defaultZone: 这个是设置与Eureka Server交互的地址,客户端的查询服务和注册服务都需要依赖这个地址。
- eureka.instance.prefer-ip-address: 在eureka中显示具体的ip
这里stock模块为什么可以找到config-server服务,是通过前面的配置
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
因为config-server再eureka中进行了注册
我这里在对应的模块写了一个接口,获取当前配置文件中的current.profile的值,因为我们之前在每一个环境中的配置文件对应的值是不同的,所以只要我们切换环境,那么配置会发生变化,current.profile值也就会发生变化
@RestController
public class StockController {
private static final String currentProjectName = "stock";
@Value("${current.profile}")
private String currentProfile;
/**
* 测试配置是否及时生效
* @return
*/
@GetMapping("/getCurrentProfile")
public String getCurrentProfile(){
return currentProjectName+":"+currentProfile==null?"null":currentProfile;
}
}
这个模块与stock模块创建一致,只是配置文件不同,因为两个模块的配置文件的地址也不同,如下
# 获取配置文件的名称
spring.cloud.config.name=userconfig
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
eureka.client.serviceUrl.defaultZone=http://localhost:8005/eureka/
eureka.instance.prefer-ip-address = true
先请求一次我们呢之前配置的那个接口,更改配置后(需要重启),再去请求一次,会发生变化
过程如下:
以上通信使用的是amqp(其实现又rabbitmq),或者你可以使用kafka
增加actuator依赖,和bus-amqp依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
需要开启actuator 的bus-refresh端点,开启bus的发现,通知功能,并配置通知消息的中间件的地址账号以及密码,即增加如下配置
# 开启actuator 的bus-refresh端点
management.endpoints.web.exposure.include= bus-refresh
#spring.cloud.bus.enabled = true
#spring.cloud.bus.trace.enabled = true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
这里我就只修改stock这一个客户端,作为列子,user客户端就不再改了
增加actuator依赖,和bus-amqp依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
需要开启actuator 的bus-refresh端点,开启bus的发现,通知功能,并配置通知消息的中间件的地址账号以及密码,即增加如下配置
# 开启actuator 的bus-refresh端点
management.endpoints.web.exposure.include= bus-refresh
#spring.cloud.bus.enabled = true
#spring.cloud.bus.trace.enabled = true
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
在使用到配置文件中的值的位置,增加注解 @RefreshScope,这个很重要,如果没有这个注解,配置还是不会刷新,如下
但是如果修改的是spring中官方配置(如改变了jdbc的连接用户没和密码等等),则不需要请求rereshe接口,但是如果是自定义的,那么就需要请求rereshs接口
这个就省略了,大家自行百度,用win或者linux都可以
http://localhost:8088/getCurrentProfile
http://localhost:9005/actuator/bus-refresh
前面本地文件中还是有eureka和config-server,现在我们也可以把eureka的配置文件上传到git服务器上本地文件只有config-server,那么其它服务就不能再通过eureka中的服务名称来寻找config-server,而且config-server也不能向eureka注册了,我们要做的就在配置文件bootstarp.properties中指定config-server的地址!
所以我们这里在我们的github的仓库中再增加一个eureka的目录和3个环境的配置文件
最后将eureka项目的application.properties文件替换成bootstrap.properties即可,内容如下
# 获取配置文件的名称
spring.cloud.config.name=eureka
spring.cloud.config.profile=dev
spring.cloud.config.label=master
# 需要知道 config-server服务的地址
spring.cloud.config.uri=http://localhost:9005
# 开启actuator 的bus-refresh端点(读取配置的客户端可以不开启)
#management.endpoints.web.exposure.include=bus-refresh
#spring.cloud.bus.enabled = true
#spring.cloud.bus.trace.enabled = true
# 接收 config-server的bus发出的配置修改的信息,以及时获取最新配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
stock和user模块的修改,即将前面配置中的
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
改为
# 需要知道 config-server服务的地址,不能通过eureka中的服务名称去找,
# 因为eureka本身还需要先知道config-server的地址,会自相矛盾
spring.cloud.config.uri=http://localhost:9005
不再通过serviceId寻找,而是通过指定的ip+port找config-server
启动顺序
config-server -----> eureka -----> stock/user
关于服务知道config-server的地址有两种方式
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=config-server
# 需要知道 config-server服务的地址,不能通过eureka中的服务名称去找,
# 因为eureka本身还需要先知道config-server的地址,会自相矛盾
spring.cloud.config.uri=http://localhost:9005
其实第一中和第二种可以混合使用,但是如果想要eureka的配置文件不在本地,那么在eureka的bootstrap.properties配置文件中就必须使用第二种方式,其它服务可以通过第一种,(但是前提是需要在config-server中指定eureka的地址),启动顺序不变,只是一开始config-server会抛出异常,是因为找不到eureka,等我们把eureka跑起来后,就可以了,大约几秒后eureka中就会有config-server这个服务,其它服务就可以根据serviceId来找config-server了,为什么其它服务不直接也使用第二种方式呢?其实可以使用,但是如果我们想给confih-server搭建集群的话,就只能使用第一种方式了,但是即使这样,还是存在一个问题,那就是eureka获取不到config-server的集群实例!
以上是我个人的一点总结,斯卡帕,如果文章有问题,还望各位看官海涵,可以在下方评论指出,谢谢!