微服务是一种架构方式,而SpringCloud与其集成的各类组件框架是实现微服务架构的一种方式,因为其基于Spring、使用便利、善于集成等优势而被广泛使用
SpringCloud主要涉及的组件包括,本文也按以下顺序来介绍:
- Eureka:注册中心
- Ribbon:负载均衡
- Hystix:熔断器
- Feign:隐藏服务的调用信息
- Zuul:服务网关
Eureka注册中心
- 基于日益复杂的互联网环境,一个项目肯定会拆分出十几,甚至数十个微服务,此时如果还人为管理这些微服务的地址,不仅开发困难,将来测试、发布上线都会非常麻烦;
- 所以我们要需要一个管理者(Eureka)来帮我们管理庞大的地址,我们一般可以把服务分为服务调用者(customer)与服务提供者(service),customer直接面对从浏览器或客户端发来的请求,之后再去调用service中的方法,那customer如何获取service的服务信息而去调用其方法呢,这就需要Eureka,service往Eureka中注册自己的信息,而customer从Eureka中获取服务提供者的信息;
- 这就好比网约车平台中滴滴司机与乘客的区别,司机给乘客提供服务,Eureka就是平台,司机是service,乘客是customer;
上图为Eureka、service、customer三者的关系
- Eureka就是管理各类微服务地址的工具,Eureka负责管理、记录service的信息,service定期向Eureka发送renew(心跳、续约),告诉Eureka我还活着,当一段时间内没有心跳了,Eureka自然会把它从服务列表中剔除;customer把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉customer;
Eureka配置流程
配置Eureka应用
在父项目中新建一个maven模块,加入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
在启动类上加入注解@EnableEurekaServer
,表明该SpringBoot是一个Eureka应用,例如:
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
在application.yml配置文件中加入配置:
server:
port: 10086
spring:
application:
name: eurekaServer # 应用名称
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka
register-with-eureka: false # 是否注册自己的信息到EurekaServer,默认是true
fetch-registry: false # 是否拉取其它服务的信息,默认是true
server:
enable-self-preservation: false # 关闭自我保护模式(缺省为打开)
eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)
配置服务提供者service
以上EurekaServer就配置好了,接下来配置提供服务者service,创建service模块,加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在service启动类上加入注解@EnableDiscoveryClient
,表示开启Eureka客户端功能;我的service直接与数据库联通,引入了通用Mapper,例如:
@EnableEurekaClient
@SpringBootApplication
@MapperScan("cn.hp.animal.mapper")
public class ServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceApplication.class, args);
}
}
在其application.yml配置文件中加入配置:
server:
port: 8080
spring:
application:
name: animal-service # 应用名称
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mydb
username: root
password: root
mybatis:
type-aliases-package: cn.hp.animal.beans
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka #,http://127.0.0.1:10087/eureka
registry-fetch-interval-seconds: 5 #5秒间隔获取服务列表
instance:
prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
#lease-expiration-duration-in-seconds: 90 #服务失效时间,默认值90秒
#lease-renewal-interval-in-seconds: 30 #服务续约(renew)的间隔,默认为30秒
要留心的配置是spring.application.name: animal-service
,该属性是指定该微服务的应用名称,未来customer调用该服务的时候就要用到;
配置服务调用者customer
一样新建customer模块,加入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
在启动类上加入注解@EnableDiscoveryClient
,表示开启Eureka客户端,例如:
@EnableDiscoveryClient
@SpringBootApplication
public class CustomApplication {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(CustomApplication.class, args);
}
}
customer多出来一个RestTemplate
并将其加入到SpringIOC容器当中,RestTemplate
是Spring自带的在模块中发送http请求的工具,customer借助其向service发送http请求调用方法;然后修改application.yml配置:
server:
port: 8088
spring:
application:
name: consumer # 应用名称
eureka:
client:
service-url: # EurekaServer地址
defaultZone: http://127.0.0.1:10086/eureka #,http://127.0.0.1:10087/eureka
registry-fetch-interval-seconds: 5 #5秒间隔获取服务列表
instance:
prefer-ip-address: false # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
三者都配置好之后,就可以往Controller中写入代码了,以下依次是customer的Controller方法与service的Controller方法:
//customer
@RequestMapping("custom")
@RestController
public class CustomController {
@Autowired
private RestTemplate template;
//eureka客户端,可以获取服务实例信息
@Autowired
private DiscoveryClient client;
@GetMapping("get/{id}")
public String getAnimals(@PathVariable("id") Integer id) {
//通过service的应用名‘animal-service’从eureka获取服务实例
ServiceInstance instance = client.getInstances("animal-service").get(0);
//通过服务实例获取ip与端口名,并拼接对应service的方法RequestMapping
//instance.getHost()可以获取到对应服务的ip地址
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/animal/get/" + id;
return template.getForObject(url,String.class);
}
//service 就是简单的Controller与请求方法
@RequestMapping("animal")
@RestController
public class AnimalController {
@Autowired
private AnimalMapper mapper;
@GetMapping("get/{id}")
public Animal getAnimals(@PathVariable("id") Integer id) {
return mapper.selectByPrimaryKey(id);
}
}
直接去请求url ‘ localhost:8088/custom/get/{1} ’ 可获取结果
高可用的Eureka Server
Eureka之前我们只配置了一个,当然也可以配置多个,形成高可用的Eureka集群,多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点;所以不论客户端访问到任意一个Eureka,都可以获取到完整的服务列表信息;
如何配置?
- 假设要搭建两条Eureka的集群,端口分别为:10086和10087
-
修改初始Eureka的配置,将
defaultZone: http://127.0.0.1:10086/eureka
改为http://127.0.0.1:10087/eureka
-
开启该Eureka Server
-
复制一个Eureka,流程:
-
再修改Eureka的yml配置文件,将端口改为
server.port: 10086
,defaultZone改为:defaultZone: http://127.0.0.1:10086/eureka
其实该配置文件被两个Eureka共同使用 -
再开启第二个Eureka应用
-
customer与service的配置也需要改动Eureka的defaultZone,例如:
eureka:
client:
service-url: # EurekaServer地址,多个地址以','隔开
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
- 以上高可用Eureka就配置好了,端口一个10086一个10087,defaultZone互相指向对方的ip地址
访问localhost:10086 或是 localhost:10087 可以看到开起了两个Eureka-Server
Robbin负载均衡
- 在企业级的项目中,例如service服务提供者的模块不仅仅只有一个,service也会形成一个集群,那么customer获取的服务列表中就会有多个,到底该访问哪一个呢?而且在访问量很大的情况下如何平均这些访问
- 这时就需要部署负载均衡工具,在多个实例列表中进行选择;Eureka中已经帮我们集成了Robbin,加入依赖与注解即可使用
负载均衡配置流程
-
首先准备启动两个service,像配置高可用的Eureka一样,先启动初始的service,再修改端口号,再复制一个service启动
可以访问 http://localhost:10086/ ,有两个ANIMAL-SERVICE正在运行
-
在customer的依赖中添加负载均衡依赖,因为是customer去请求service,负载均衡要帮助customer去选择访问哪一个service;加入:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
- 在RestTemplate的配置方法上添加
@LoadBalanced
注解:
@EnableDiscoveryClient
@SpringBootApplication
public class CustomApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(CustomApplication.class, args);
}
}
- 修改customer的Controller里的方法,可以看到之前用client获取ip与端口的方式被淘汰,而只需要在url中指定应用名
animal-service
,ribbon即可定位到相应service应用
@RequestMapping("custom")
@RestController
public class CustomController {
@Autowired
private RestTemplate template;
@GetMapping("get/{id}")
public String getAnimals(@PathVariable("id") Integer id) {
/*ServiceInstance instance = client.getInstances("animal-service").get(0);
String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/animal/get/" + id;*/
//负载均衡:
String url = "http://animal-service/animal/get/" + id;
return template.getForObject(url, String.class);
}
ribbon在底层会通过应用名获取对应应用的ip与端口
Hystrix熔断器
当用户访问量很大时,service很可能会被堵塞,如果customer继续请求service的话,不保证service不会宕机,Hystrix可以判断某些服务反应慢或者存在大量超时的情况,能够主动熔断,防止整个系统被拖垮,可以直接拒绝后续的请求,当后续服务压力变低时,又可以实现重连,能够对后续服务灵活的调用
Hystrix配置流程
- 在customer中引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
- 在customer主类中加入注解
@EnableCircuitBreaker
,而注解@EnableCircuitBreaker
+@EnableDiscoveryClient
+@SpringBootApplication
等价于@SpringCloudApplication
,所以只需要一个注解即可
//@EnableCircuitBreaker //开启熔断器功能
//@EnableDiscoveryClient
//@SpringBootApplication
@SpringCloudApplication
public class CustomApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(CustomApplication.class, args);
}
- 修改customer的Controller,在方法上加入注解
@HystrixCommand(fallbackMethod = "XXX")
,fallbackMethod
设定熔断器的降级服务方法(降级服务就是不能访问后续服务时,进入另一个方法,该方法可以返回友好提示或是错误页面)
@RequestMapping("custom")
@RestController
public class CustomController {
@Autowired
private RestTemplate template;
@HystrixCommand(fallbackMethod = "fallback") //声明该方法使用默认的降级方法
@GetMapping("get/{id}")
public String getAnimals(@PathVariable("id") Integer id) {
String url = "http://animal-service/animal/get/" + id;
return template.getForObject(url, String.class);
}
//熔断的降级逻辑方法必须跟正常逻辑方法保证:相同的参数列表和返回值声明
public String fallback(Integer id) {
return "服务器拥挤!请稍后访问!";
}
}
- 还是第三个步骤,刚才把降级服务方法定义在了业务方法上,这样比较繁琐;所以我们可以把fallbackMethod定义在类上,实现默认的fallback方法:
@DefaultProperties(defaultFallback = "fallback") //声明默认降级服务方法
@RequestMapping("custom")
@RestController
public class CustomController {
@Autowired
private RestTemplate template;
@HystrixCommand //使用默认的降级方法
@GetMapping("get/{id}")
public String getAnimals(@PathVariable("id") Integer id) {
String url = "http://animal-service/animal/get/" + id;
return template.getForObject(url, String.class);
}
/*如在类上定义了默认降级方法,降级方法可以不用传任何参数,
以匹配更多方法,但是返回值一定与目标方法一致*/
public String fallback() {
return "服务器拥挤!请稍后访问!";
}
}
- 熔断器肯定有一个超时参数,一旦访问service方法超时,则熔断,接下来配置超时,在customer的yml配置文件中加入:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
# 设置hystrix的超时时间为3秒
# hystrix默认的超时时间为1秒
可以在service的Controller方法中让其睡上几秒,验证熔断是否起作用
Feign
Feign可以将customer发给service的请求进行隐藏;你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做;为什么这么干呢,之前使用Ribbon的负载均衡功能,大大简化了远程调用时的代码:
String url = "http://animal-service/animal/get/" + id;
return template.getForObject(url, String.class);
虽说只有两行代码,如果每一次都要自己手动写应用名称animal-service
与手动拼接参数,代码还不够精简,所以需要使用到Feign,通过调用接口中方法来实现请求service
Feign的配置流程
- customer中导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
- 在启动类上开启Feign,Feign中已经自动集成了Ribbon负载均衡,因此不需要自己定义RestTemplate
@EnableFeignClients
@SpringCloudApplication
public class CustomApplication {
public static void main(String[] args) {
SpringApplication.run(CustomApplication.class, args);
}
}
- customer通过调用Feign接口中的方法来请求service,先不急于修改Controller
- 新建一个接口,Feign会通过动态代理,帮我们生成实现类
@FeignClient
声明这是一个Feign客户端,同时通过value
属性指定service应用名称- 接口中的定义的
@GetMapping()
与请求service中目标方法的映射一一对应
@FeignClient(value = "animal-service")
public interface ServiceClient {
@GetMapping("animal/get/{id}")
String getAnimal(@PathVariable("id") Integer id);
}
- 再来修改Controller,Controller只注入该接口,目标方法调用接口中方法,的确隐藏了请求service的url信息
@RequestMapping("custom")
@RestController
public class CustomController {
@Autowired
private ServiceClient client;
@GetMapping("get/{id}")
public String getAnimals(@PathVariable("id") Integer id) {
return client.getAnimal(id);
}
}
以上Feign配置完成
Feign对Ribbon负载均衡与Hystix熔断器的支持
- Feign已经封装了Ribbon,所以在customer的yml加入负载均衡配置即可:
ribbon:
ConnectionTimeOut: 500 #建立连接时间
ReadTimeOut: 2000 #feign中ribbon配置
- Feign默认也有对Hystix的集成:
- 2.1加入配置:
feign:
hystrix:
enabled: true # 开启Feign的熔断功能
- 2.2但Feign中的Fallback方法配置不像Ribbon中那样简单了;首先要定义一个类,实现刚才编写的ServiceClient ,作为fallback方法的处理类,例如:
@Component
public class ServiceClientFallBack implements ServiceClient {
//getAnimal方法的降级方法
@Override
public String getAnimal(Integer id) {
return "服务器繁忙,请稍后访问!";
}
}
- 2.3然后在ServiceClient的
@FeignClient
中,指定刚才编写的实现类即可,例如:
@FeignClient(value = "animal-service",
fallback = ServiceClientFallBack.class)
public interface ServiceClient {
@GetMapping("animal/get/{id}")
String getAnimal(@PathVariable("id") Integer id);
}
Zuul服务网关
Zuul是Netlix开源的微服务网关,它可以和Eureka、Ribbon、Hystrix等组件配合使用;Zuul部署在项目中后会直接面对所有从客户端发来的请求,接收到请求后通过Zuul中的过滤器判断该请求是否符合要求,符合则请求后续服务;Zuul的核心也是一系列过滤器,可以完成以下功能:
- 身份认证与安全:识别每个资源的验证要求,并拒绝那些与要求不符的请求
- 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图
- 动态路由:动态地将请求路由到不同的后端集群
- 压力测试:逐渐增加指向集群的流量,以了解性能
- 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求
- 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到内部集群
- 多区域弹性:跨越AWS Region进行请求路由,旨在实现ELB(Elastic Load Balancing)使用的多样化,以及让系统的边缘更贴近系统的使用者
Zuul加入后的项目架构:
Zuul的配置流程:
- 首先还是导入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
- 在启动类中加入注解
@EnableZuulProxy
,表示开启zuul网关功能,同时也要开启Eureka客户端功能,例如:
@EnableDiscoveryClient
@EnableZuulProxy //开启Zuul的网关功能
@SpringBootApplication
public class ZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
}
- 在配置文件中加入配置,
zuulService
该命名指路由id,path
定义url访问格式,例如localhost:10010/zuulAnimal/**
格式的url才可被zuul接受,而serviceId
指定我要请求的后续应用名,配置如下:
server:
port: 10010 #服务端口
spring:
application:
name: gateway #指定服务名
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
registry-fetch-interval-seconds: 5 # 获取服务列表的周期:5s
instance:
prefer-ip-address: true # 当调用getHostname获取实例的hostname时,返回ip而不是host名称
ip-address: 127.0.0.1 # 指定自己的ip信息,不指定的话会自己寻找
zuul:
routes:
zuulService: # 这里是路由id,随意写
path: /zuulAnimal/** # 这里是映射路径
serviceId: animal-service # 指定服务名称
以上Zuul的基本配置就已完成
当开启zuul服务后
因为我的zuul后续直接请求service(服务提供端),所以customer没必要开了,直接访问 http://localhost:10010/zuulAnimal/animal/get/10
zuul底层将该url转为 localhost:8081/animal/get/10
当然之前的path
参数也可以不配置,zuul有默认的路由规则
zuul的默认路由规则
默认情况下,一切去往后续服务的映射路径就是后续的服务名本身,配置例如:
#简化的路由配置,把routes下面的名字指定为应用名,zuul会通过该应用名去寻找该应用的ip
zuul:
routes:
#如果 animal-service: 不指定路由规则,则默认的路由规则是 /animal-service/** ,也就是以定义的应用名作为路由规则
animal-service:
访问结果:
zuul路由前缀
单纯在请求url中加入请求前缀,prefix
指定了路由的前缀,这样在发起请求时,路径就要以/api
开头,strip-prefix
指是否在转换url时截取映射路径,配置例如:
zuul:
prefix: /api#如果定义prefix参数,表名请求url要加上该前缀才能被zuul处理
routes:
service:
path: /zuulAnimal/** #映射路径
serviceId: animal-service #指定后续服务名称
#strip-prefix: false #不截取path路径中的/zuulAnimal,默认为true
由 http://localhost:10010/api/zuulAnimal/animal/get/51 转为 http://localhost:8081/animal/get/51
zuul过滤器
- Zuul作为网关的其中一个重要功能,就是实现请求的鉴权;而这个动作我们往往是通过Zuul提供的过滤器来实现的
- ZuulFilter是过滤器的顶级父类,在这里看一下其中定义的4个最重要的方法:
public abstract ZuulFilter implements IZuulFilter{
abstract public String filterType();
abstract public int filterOrder();
boolean shouldFilter();// 来自IZuulFilter
Object run() throws ZuulException;// IZuulFilter
}
shouldFilter
:返回一个Boolean
值,判断该过滤器是否需要执行;返回true执行,返回false不执行run
:过滤器的具体业务逻辑。filterType
:返回字符串,代表过滤器的类型。包含以下4种:pre
:请求在被路由之前执行routing
:在路由请求时调用post
:在routing和errror过滤器之后调用error
:处理请求时发生错误调用
filterOrder
:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高
过滤器执行生命周期
- 正常流程:
- 请求到达首先会经过pre类型过滤器,而后到达routing类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器,而后返回响应
- 异常流程:
- 整个过程中,pre或者routing过滤器出现异常,都会直接进入error过滤器,再error处理完毕后,会将请求交给POST过滤器,最后返回给用户
- 如果是error过滤器自己出现异常,最终也会进入POST过滤器,而后返回
- 如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和routing不同的是,请求不会再到达POST过滤器了
zuul自定义过滤器
写一个自定义过滤器类:
@Component
public class Filter extends ZuulFilter {
@Override
public String filterType() {
return null;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
//判断该过滤器是否需要执行
return true;
}
@Override
public Object run() throws ZuulException {
//获取请求上下文
RequestContext ctx = RequestContext.getCurrentContext();
//获取request
HttpServletRequest request = ctx.getRequest();
//获取请求参数
String token = request.getParameter("access-token");
//判断是否存在
if (StringUtils.isBlank(token)) {
//返回403
ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
//不存在,未登陆,则拦截
ctx.setSendZuulResponse(false);
}
return null;
}
}
访问后:
- Zuul中默认就已经集成了Ribbon负载均衡和Hystix熔断机制;但是所有的超时策略都是走的默认值,比如熔断超时时间只有1S,很容易就触发了;因此手动进行配置:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 熔断超时时长:6000ms
ribbon:
ConnectionTimeOut: 500 # 连接超时时间(ms)
ReadTimeOut: 4000 # 通信超时时间(ms)
MaxAutoRetriesNextServer: 2 # 同一服务不同实例的重试次数
- 以上就是Zuul
Spring Cloud Config
因为在开发中存在大量的微服务,一个微服务对应一套配置信息,这些配置信息庞大又难以管理,所以出现了 Spring Cloud Config
以上是 Spring 官方的解释,Spring Cloud Config 可以分为服务器与客户端,服务器可以从远程仓库中获取其他微服务的配置信息(例如下图),而 client 客户端(例如服务提供者、消费者、Eureka 服务器)可以从服务器获取各自的配置信息,Spring Cloud Config 就是一个微服务配置信息管理工具
使用流程,首先创建一个 git 远程仓库:
使用码云创建一个仓库,将其下载到本机,加入一些 yml 配置文件,例如:
选择 config-client.yml 为例子:
在使用 git 工具将该文件夹 push 到仓库中,这样仓库就创建好了
创建 Config Server 服务器
- 首先导入依赖,对应的 spring boot 版本是 2.2.7 :
maven 仓库:Spring Cloud Config Server 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
- 在主类上加注解,开启 config server
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
- 在 application.yml 中配置远程仓库地址
server:
port: 3344
spring:
application:
name: springcloud-config-server
#连接远程仓库
cloud:
config:
server:
git:
uri: https://gitee.com/ xxx /springcloud-config.git #gitee的https链接
以上三步服务器就配置好了
创建 Config Client 客户端
- 首先导入依赖:
maven仓库:Spring Cloud Starter Config 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
- 写配置文件,在 application.yml 写微服务独有的配置信息,创建 bootstrap.yml 文件写入与服务器的连接信息:
#application.yml
#用户级别的配置
spring:
application:
name: config-client
#bootstrap.yml
#系统级别的配置
spring:
cloud:
config:
name: config-client #需要从git上读取的资源名称,不要后缀
profile: dev #选择配置环境
label: master #选择git上的分支
uri: http://localhost:3344 #config server 的IP地址与端口号
以上两步客户端就配置好了
接下来测试客户端,创建一个 ConfigClientController ,里面配置的三个属性值都在远程仓库中,服务器先从远程获取配置,客户端再去向服务器获取对应配置信息
@RestController
public class ConfigClientController {
@Value("${spring.application.name}")
private String applicationName;
@Value("${eureka.client.service-ur1.defaultZone}")
private String eurekaServer;
@Value("${server.port}")
private String port;
@GetMapping("getProfilesInfo")
public String getInfo() {
return "applicationName:" + applicationName + ",eurekaServer:" + eurekaServer + ",port:" + port;
}
}
测试结果,之前客户端选择了开发环境,端口的确为 3355,访问测试方法,拿到的结果与客户端dev配置信息一致:
开发中存在很多微服务,例如每个服务提供者都要注册 Eureka,这样相同的信息就可以通过 config server 去管理,对于每个微服务都不同的配置(例如端口),可以在 application.yml 中独立配置,Spring Cloud Config 为管理配置提供了极大的便利