SpringCloud(2)---入门篇
SpringCloud(6)---熔断降级理解、Hystrix实战
一、概念
1、为什么需要熔断降级
(1)需求背景
它是系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案。
在一个分布式系统里,一个服务依赖多个服务,可能存在某个服务调用失败,比如超时、异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败。
比如:某微服务业务逻辑复杂,在高负载情况下出现超时情况。
内部条件:程序bug导致死循环、存在慢查询、程序逻辑不对导致耗尽内存
外部条件:黑客攻击、促销、第三方系统响应缓慢。
(2)解决思路
解决接口级故障的核心思想是优先保障核心业务和优先保障绝大部分用户。比如登录功能很重要,当访问量过高时,停掉注册功能,为登录腾出资源。
(3)解决策略
熔断,降级,限流,排队。
2、什么是熔断
一般是某个服务故障或者是异常引起的,类似现实世界中的‘保险丝’,当某个异常条件被触发,直接熔断整个服务,而不是一直等到此服务超时,为了防止防止整个系统的故障,
而采用了一些保护措施。过载保护。比如A服务的X功能依赖B服务的某个接口,当B服务接口响应很慢时,A服务X功能的响应也会被拖慢,进一步导致了A服务的线程都卡在了X功能
上,A服务的其它功能也会卡主或拖慢。此时就需要熔断机制,即A服务不在请求B这个接口,而可以直接进行降级处理。
3、什么是降级
服务器当压力剧增的时候,根据当前业务情况及流量,对一些服务和页面进行有策略的降级。以此缓解服务器资源的的压力,以保证核心业务的正常运行,同时也保持了客户和
大部分客户的得到正确的相应。
自动降级:超时、失败次数、故障、限流
(1)配置好超时时间(异步机制探测回复情况);
(2)不稳的的api调用次数达到一定数量进行降级(异步机制探测回复情况);
(3)调用的远程服务出现故障(dns、http服务错误状态码、网络故障、Rpc服务异常),直接进行降级。
人工降级:秒杀、双十一大促降级非重要的服务。
4、熔断和降级异同
相同点:
1)从可用性和可靠性触发,为了防止系统崩溃
2)最终让用户体验到的是某些功能暂时不能用
不同点:
1)服务熔断一般是下游服务故障导致的,而服务降级一般是从整体系统负荷考虑,由调用方控制
2)触发原因不同,上面颜色字体已解释
5、熔断到降级的流程讲解
Hystrix提供了如下的几个关键参数,来对一个熔断器进行配置:
circuitBreaker.requestVolumeThreshold //滑动窗口的大小,默认为20
circuitBreaker.sleepWindowInMilliseconds //过多长时间,熔断器再次检测是否开启,默认为5000,即5s钟
circuitBreaker.errorThresholdPercentage //错误率,默认50%
3个参数放在一起,所表达的意思就是:
每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。
这里面有个很关键点,达到熔断之后,那么后面它就直接不去调该微服务。那么既然不去调该微服务或者调的时候出现异常,出现这种情况首先不可能直接把错误信息传给用户,所以针对熔断
我们可以考虑采取降级策略。所谓降级,就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。
这样做,虽然服务水平下降,但好歹可用,比直接挂掉要强,当然这也要看适合的业务场景。
二、Hystrix实战
使用到的组件包括:Eureka、Feign包括以下三个项目:
(1)Eureka-server: 7001 注册中心
(2)product-server :8001 商品微服务
(3)order-server : 9001 订单微服务
注册中心、商品微服务、在之前博客都已搭建,这里就不重复写。这里只写order-server微服务。具体可以看上篇博客:SpringCloud(5)---Feign服务调用
1、pom.xml
<!--hystrix依赖,主要是用 @HystrixCommand -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2、application.yml

server:
port: 9001 #指定注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/ #服务的名称
spring:
application:
name: order-service #开启feign支持hystrix (注意,一定要开启,旧版本默认支持,新版本默认关闭)
# #修改调用超时时间(默认是1秒就算超时)
feign:
hystrix:
enabled: true
client:
config:
default:
connectTimeout: 2000
readTimeout: 2000

3、SpringBoot启动类

@SpringBootApplication
@EnableFeignClients
//添加熔断降级注解
@EnableCircuitBreaker
public class OrderApplication { public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
} }

4、ProductClient

/**
* 商品服务客户端
* name = "product-service"是你调用服务端名称
* fallback = ProductClientFallback.class,后面是你自定义的降级处理类,降级类一定要实现ProductClient
*/
@FeignClient(name = "product-service",fallback = ProductClientFallback.class)
public interface ProductClient { //这样组合就相当于http://product-service/api/v1/product/find
@GetMapping("/api/v1/product/find")
String findById(@RequestParam(value = "id") int id); }

5、ProductClientFallback降级处理类

/**
* 针对商品服务,错降级处理
*/
@Component
public class ProductClientFallback implements ProductClient { @Override
public String findById(int id) { System.out.println("ProductClientFallback中的降级方法"); //这对gai该接口进行一些逻辑降级处理........
return null;
}
}

6、OrderController类
注意:fallbackMethod = "saveOrderFail"中的saveOrderFail方法中的参数类型,个数,顺序要和save一模一样,否则会报找不到saveOrderFail方法。

@RestController
@RequestMapping("api/v1/order")
public class OrderController { @Autowired
private ProductOrderService productOrderService; @RequestMapping("save")
//当调用微服务出现异常会降级到saveOrderFail方法中
@HystrixCommand(fallbackMethod = "saveOrderFail")
public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId){ return productOrderService.save(userId, productId);
} //注意,方法签名一定要要和api方法一致
private Object saveOrderFail(int userId, int productId){ System.out.println("controller中的降级方法"); Map<String, Object> msg = new HashMap<>();
msg.put("code", -1);
msg.put("msg", "抢购人数太多,您被挤出来了,稍等重试");
return msg;
}
}

7、测试
(1)正常情况
先将订单服务(order)和商品服务(product)同时启动,如图:
订单服务调用商品服务正常
(2)异常情况
此刻我将商品微服务停掉:只启动订单微服务,这时去调用商品服务当然会出现超时异常情况。
在调接口,发现已经成功到降级方法里
在看controller中的降级方法和ProductClientFallback降级方法的实现先后顺序,它们的顺序是不固定的,有可能controller中降级方法先执行,也可能ProductClientFallback降级方法先执行。
具体要看哪个线程先获得cpu执行权。
三、结合redis模拟熔断降级服务异常报警通知实战
主要是完善完善服务熔断处理,报警机制完善结合redis进行模拟短信通知用户下单失败。
1、pom.xml
<!--springboot整合redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、application.yml

#服务的名称
#redis
spring:
application:
name: order-service
redis:
database: 0
host: 127.0.0.1
port: 6379
timeout: 2000

3、OrderController类
主要看降级方法的不同

@RestController
@RequestMapping("api/v1/order")
public class OrderController { @Autowired
private ProductOrderService productOrderService; //添加bean
@Autowired
private StringRedisTemplate redisTemplate; @RequestMapping("save")
//当调用微服务出现异常会降级到saveOrderFail方法中
@HystrixCommand(fallbackMethod = "saveOrderFail")
public Object save(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId,HttpServletRequest request){ return productOrderService.save(userId, productId);
} //注意,方法签名一定要要和api方法一致
private Object saveOrderFail(int userId, int productId, HttpServletRequest request){ //监控报警
String saveOrderKye = "save-order";
//有数据代表20秒内已经发过
String sendValue = redisTemplate.opsForValue().get(saveOrderKye);
final String ip = request.getRemoteAddr(); //新启动一个线程进行业务逻辑处理
new Thread( ()->{
if (StringUtils.isBlank(sendValue)) {
System.out.println("紧急短信,用户下单失败,请离开查找原因,ip地址是="+ip);
//发送一个http请求,调用短信服务 TODO
redisTemplate.opsForValue().set(saveOrderKye, "save-order-fail", 20, TimeUnit.SECONDS); }else{
System.out.println("已经发送过短信,20秒内不重复发送");
}
}).start(); Map<String, Object> msg = new HashMap<>();
msg.put("code", -1);
msg.put("msg", "抢购人数太多,您被挤出来了,稍等重试");
return msg;
} }

4、测试
当20秒内连续发请求会提醒已发短信。
官方文档:https://github.com/Netflix/Hystrix/wiki/Configuration#execution.isolation.strategy
SpringCloud(7)---网关概念、Zuul项目搭建
项目代码GitHub地址:https://github.com/yudiandemingzi/spring-cloud-study
一、网关概念
1、什么是路由网关
网关是系统的唯一对外的入口,介于客户端和服务器端之间的中间层,处理非业务功能 提供路由请求、鉴权、监控、缓存、限流等功能。它将"1对N"问题转换成了"1对1”问题。
通过服务路由的功能,可以在对外提供服务时,只暴露 网关中配置的调用地址,而调用方就不需要了解后端具体的微服务主机。
2、为什么要使用微服务网关
不同的微服务一般会有不同的网络地址,而客户端可能需要调用多个服务接口才能完成一个业务需求,若让客户端直接与各个微服务通信,会有以下问题:
(1)客户端会多次请求不同微服务,增加了客户端复杂性
(2)存在跨域请求,处理相对复杂
(3)认证复杂,每个服务都需要独立认证
(4)难以重构,多个服务可能将会合并成一个或拆分成多个
3、网关的优点
微服务网关介于服务端与客户端的中间层,所有外部服务请求都会先经过微服务网关客户只能跟微服务网关进行交互,无需调用特定微服务接口,使得开发得到简化
总的理解网关优点
服务网关 = 路由转发 + 过滤器
(1)路由转发:接收一切外界请求,转发到后端的微服务上去。
(2)过滤器:在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成(其实路由转发也是通过过滤器实现的)。
4、服务网关技术选型
引入服务网关后的微服务架构如上,总体包含三部分:服务网关、open-service和service。
(1)总体流程
服务网关、open-service和service启动时注册到注册中心上去;
用户请求时直接请求网关,网关做智能路由转发(包括服务发现,负载均衡)到open-service,这其中包含权限校验、监控、限流等操作
open-service聚合内部service响应,返回给网关,网关再返回给用户
(2)引入网关的注意点
增加了网关,多了一层转发(原本用户请求直接访问open-service即可),性能会下降一些(但是下降不大,通常,网关机器性能会很好,而且网关与open-service的访问通常
是内网访问,速度很快);
(3)服务网关基本功能
智能路由:接收外部一切请求,并转发到后端的对外服务open-service上去;
注意:我们只转发外部请求,服务之间的请求不走网关,这就表示全链路追踪、内部服务API监控、内部服务之间调用的容错、智能路由不能在网关完成;
当然,也可以将所有的服务调用都走网关,那么几乎所有的功能都可以集成到网关中,但是这样的话,网关的压力会很大,不堪重负。
权限校验:可在微服务网关上进行认证,然后在将请求转发给微服务,无须每个微服务都进行认证,不校验服务内部的请求。服务内部的请求有必要校验吗?
API监控:只监控经过网关的请求,以及网关本身的一些性能指标(例如,gc等);
限流:与监控配合,进行限流操作;
API日志统一收集:类似于一个aspect切面,记录接口的进入和出去时的相关日志。
二、Zuul项目搭建
使用到的组件包括:Eureka、Feign、Zuul,包括以下四个项目:
(1)Eureka-server: 7001 注册中心
(2)product-server :8001 商品微服务
(3)order-server : 9001 订单微服务
(4)zuul-gateway : 6001 Zuul网关
注册中心、商品微服务、order在之前博客都已搭建,这里就不重复写。这里只写zuul-gateway微服务。
1、pom.xml

<!--客户端jar包,这个在订单微服务,商品微服务都要添加-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <!--zuuljar包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

2、application.yml

server:
port: 6001 #服务的名称
spring:
application:
name: zuul-gateway #指定注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/ #自定义路由映射
zuul:
routes:
order-service: /apigateway/order/**
product-service: /apigateway/product/**
#统一入口为上面的配置,其他入口忽略
ignored-patterns: /*-service/**
#忽略整个服务,对外提供接口
ignored-services: order-service

3、SpringBoot启动类

@SpringBootApplication
//加上网关注解
@EnableZuulProxy
public class ZuulServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulServerApplication.class, args);
}
}

4、测试
(1)直接订单服务调商品服务
(2)通过Zuul网关实现订单接口调商品服务
5、注意些细节
(1)url不能重复,否则会覆盖
order-service: /apigateway/order/**
product-service: /apigateway/product/**
(2)通过zuul后,request中的cookie值获取不到,那是因为网关给过滤掉了。

@RequestMapping("list")
public void list(@RequestParam("user_id")int userId, @RequestParam("product_id") int productId, HttpServletRequest request){
String token = request.getHeader("token");
String cookie = request.getHeader("cookie");
//会发现token值能够获取,cookie无法获取,原因是因为网关会过滤掉敏感词
System.out.println("token="+token);
System.out.println("cookie="+cookie);
}

想要不过滤掉cookie值那么在配置里配置
zuul:
#处理http请求头为空的问题
sensitive-headers:
6、问题
自己遇到两个问题记录下,后期再来思考解决。
1、现在通过订单服务地址可以直接访问订单微服务,如何配置成订单微服务不能直接服务,只能通过网关访问。
思考,是不是以后订单微服务配置到内网就不会有这个问题了。
2、当我的订单服务调商品服务异常时,直接访问订单微服务熔断降级能够完成,通过网关竟然直接报异常了。
我在商品微服务相关接口添加:
//睡眠两秒,微服务默认一秒就超时,所以会到降级方法
TimeUnit.SECONDS.sleep(2);
直接调订单服务,降级信息返回正常。如果通过网关访问。
返回的是异常,这不是很蛋疼吗,总是有解决办法让降级信息返回来的,以后解决来再来写。
zuul权限校验、接口限流
项目代码GitHub地址:https://github.com/yudiandemingzi/spring-cloud-study
一、权限校验搭建
正常项目开发时,权限校验可以考虑JWT和springSecurity结合进行权限校验,这个后期会总结,这里做个基于ZuulFilter过滤器进行一个简单的权限校验过滤。
对于组件zuul中,其实带有权限认证的功能,那就是ZuulFilter过滤器。ZuulFilter是Zuul中核心组件,通过继承该抽象类,覆写几个关键方法达到自定义调度请求的作用
使用到的组件包括:Eureka、Feign、Zuul,包括以下四个项目:
(1)Eureka-server: 7001 注册中心
(2)product-server : 8001 商品微服务
(3)order-server : 9001 订单微服务
(4)zuul-gateway : 6001 Zuul网关
有关四个服务的基本配置我这里就不写了,具体可以看之前几篇博客,这里只写LoginFilter权限校验类
1、LoginFilter类

/**
* 登录过滤器
*记得类上加Component注解
*/
@Component
public class LoginFilter extends ZuulFilter { /**
* 过滤器类型,前置过滤器
*/
@Override
public String filterType() {
return PRE_TYPE;
} /**
* 过滤器顺序,越小越先执行
*/
@Override
public int filterOrder() {
return 4;
} /**
* 过滤器是否生效
* 返回true代表需要权限校验,false代表不需要用户校验即可访问
*/
@Override
public boolean shouldFilter() { //共享RequestContext,上下文对象
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest(); System.out.println(request.getRequestURI());
//需要权限校验URL
if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
return true;
} else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())) {
return true;
} else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())) {
return true;
}
return false;
} /**
* 业务逻辑
* 只有上面返回true的时候,才会进入到该方法
*/
@Override
public Object run() throws ZuulException { //JWT
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest(); //token对象,有可能在请求头传递过来,也有可能是通过参数传过来,实际开发一般都是请求头方式
String token = request.getHeader("token"); if (StringUtils.isBlank((token))) {
token = request.getParameter("token");
}
System.out.println("页面传来的token值为:" + token);
//登录校验逻辑 如果token为null,则直接返回客户端,而不进行下一步接口调用
if (StringUtils.isBlank(token)) {
// 过滤该请求,不对其进行路由
requestContext.setSendZuulResponse(false);
//返回错误代码
requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
return null;
}
}

2、关键说明
(1)方法说明
filterType : filter类型,分为pre、error、post、 route
filterOrder: filter执行顺序,通过数字指定,数字越小,执行顺序越先
shouldFilter: filter是否需要执行 true执行 false 不执行
run : filter具体逻辑(上面为true那么这里就是具体执行逻辑)
(2)filter类型说明
pre: 请求执行之前filter
route: 处理请求,进行路由
post: 请求处理完成后执行的filter
error: 出现错误时执行的filter
3、测试
先在请求头和传参都不传token,校验失败:返回401状态码
在参数的时候传入token值
看后台输出
说明模拟校验通过,返回用户信息。
二、接口限流搭建
接口限流可以在nginx层面做限流,也可以在网关层面做限流,这里在网关层面做限流,基于guava框架来做网关限流。
先对guava框架限流的概念进行讲解下:
它的大致意思就是每一个请求进来先到桶里去拿令牌,拿到令牌的请求放行,假设你设置了1000个令牌,如果拿完了,那么后面来调接口的请求就需要排队等有新的令牌才能调用该接口。
OrderRateLimiterFilter限流过滤类

/**
* 订单限流
*其它和上面都一样,只是run()中逻辑不一样
*/
@Component
public class OrderRateLimiterFilter extends ZuulFilter { //每秒产生1000个令牌
private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000); @Override
public String filterType() {
return PRE_TYPE;
} @Override
public int filterOrder() {
return -4;
} @Override
public boolean shouldFilter() {
RequestContext requestContext = RequestContext.getCurrentContext();
HttpServletRequest request = requestContext.getRequest(); //只对订单接口限流
if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) {
return true;
}
return false;
} @Override
public Object run() throws ZuulException {
RequestContext requestContext = RequestContext.getCurrentContext(); //就相当于每调用一次tryAcquire()方法,令牌数量减1,当1000个用完后,那么后面进来的用户无法访问上面接口
//当然这里只写类上面一个接口,可以这么写,实际可以在这里要加一层接口判断。
if (!RATE_LIMITER.tryAcquire()) {
requestContext.setSendZuulResponse(false);
//HttpStatus.TOO_MANY_REQUESTS.value()里面有静态代码常量
requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());
}
return null;
}
}

mysql实现配置中心
本公司配置数据的管理是通过mysql进行配置管理,因为已经搭建好了,所以自己动手重新搭建一遍,熟悉整个流程。有关项目源码后期会补上github地址
微服务要实现集中管理微服务配置、不同环境不同配置、运行期间也可动态调整、配置修改后可以自动更新的需求,Spring Cloud Config同时满足了以上要求。
项目代码GitHub地址:https://github.com/yudiandemingzi/spring-cloud-study
一、项目搭建
本次主要用三个微服务
(1)Eureka-server: 7001 注册中心
(2)config-server : 5001 配置中心
(3)product-server : 8001 商品微服务
1、Eureka-server注册中心
注册中心很简单,这里不在重复些,注册中心没有变化。可以看之前写的博客 : SpringCloud(3)---Eureka服务注册与发现
2、配置中心微服务
1、pom.xml

<!--服务中心jar包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <!--配置中心jar包-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency> <!--连接msql数据库相关jar包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>

2、application.yml

#服务名称
server:
port: 5001 #连接配置信息
spring:
application:
name: config-server-jdbc
profiles:
active: jdbc
cloud:
config:
server:
default-label: dev
jdbc:
sql: SELECT akey , avalue FROM config_server where APPLICATION=? and APROFILE=? and LABEL=?
#####################################################################################################
# mysql 属性配置
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test
username: root
password: root
##################################################################################################### #指定注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/

这里主要讲下连接配置信息
(1)spring.profiles.active=jdbc,自动实现JdbcEnvironmentRepository。
(2)sql语句自定义,否则会默认为“SELECT KEY, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?”,具体可以参考JdbcEnvironmentRepository实现。
(3)本人数据库建表为config_server,由于key,value和profile是mysql关键字,所以我都在最前面加了a。当然表名字段名都可以自定义。
(4) {application} 对应客户端的"spring.application.name"属性;
{aprofile} 对应客户端的 "spring.profiles.active"属性(逗号分隔的列表); 和
{label} 对应服务端属性,这个属性能标示一组配置文件的版本.
(5)只要select出来是两个字段,框架会自动包装到environment的map<key,value>。
3、mysql数据
4、springboot启动类
添加@EnableConfigServer注解

@SpringBootApplication
@EnableConfigServer
public class ConfigserverApplication { public static void main(String[] args) {
SpringApplication.run(ConfigserverApplication.class, args);
}
}

3、product-service微服务
1、pom.xml

<!--服务中心jar-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <!--配置中心客户端jar-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>

2、bootstrap.yml

#指定注册中心地址
eureka:
client:
serviceUrl:
defaultZone: http://localhost:7001/eureka/ #服务的名称
spring:
application:
name: product-service
#指定从哪个配置中心读取
cloud:
config:
discovery:
service-id: config-server-jdbc
enabled: true
profile: dev
label: dev server:
port: 8001

这里为什么用bootstrap.yml而不用application.yml,是因为若application.yml 和bootStrap.yml 在同一目录下,
则bootStrap.yml 的加载顺序要高于application.yml,即bootStrap.yml 会优先被加载。
为何需要把 config server 的信息放在 bootstrap.yml 里?
当使用 Spring Cloud 的时候,配置信息一般是从 config server 加载的,为了取得配置信息(比如密码等),你需要一些提早的或引导配置。
因此,把 config server 信息放在 bootstrap.yml,用来加载真正需要的配置信息。
3、ConfigController类(测试用)

@RestController
@RequestMapping("/api/v1/product")
public class ConfigController { @Value("${item_url}")
private String url; /**
* 输出url
*/
@RequestMapping("url")
public void list(){ System.out.println(url);
}

4、测试
通过访问:http://localhost:8001/api/v1/product/url 进入断点。
SpringCloud(2)---入门篇的更多相关文章
- Spring Cloud(一):入门篇
Spring Cloud 简介 Spring Cloud 是一个基于 Spring Boot 实现的微服务架构开发工具,可以快速构建分布式系统中的某些常用模式,如配置管理.服务治理.断路器.智能路由. ...
- Springboot快速入门篇,图文并茂
Springboot快速入门篇,图文并茂 文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star!搜索关注微信公众号 [码出Offer] 领取各种学习资料! image-20 ...
- Spring Cloud Alibaba(1)---入门篇
Spring Cloud Alibaba入门篇 有关微服务的一些概念的东西我这里就不再阐述了,因为之前在写Spring Cloud系列的时候都有详细写过. 具体地址: Spring Cloud系列博客 ...
- Membership三步曲之入门篇 - Membership基础示例
Membership 三步曲之入门篇 - Membership基础示例 Membership三步曲之入门篇 - Membership基础示例 Membership三步曲之进阶篇 - 深入剖析Pro ...
- spring boot(一):入门篇
构建微服务:Spring boot 入门篇 什么是spring boot Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...
- 1. web前端开发分享-css,js入门篇
关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人与人的教育背景与成长环境心理活动都有差别,但就别人的心得再结合自己的特点,然后探索适合自己的学 ...
- 一个App完成入门篇(七)- 完成发现页面
第七章是入门篇的倒数第二篇文章了,明天整个APP将进入收官. 本节教程主要要教会大家使用二维码扫描和用do_WebView组件加在html页面. 导入项目 do_WebView组件 扫描功能 自定义事 ...
- [原创]Linq to xml增删改查Linq 入门篇:分分钟带你遨游Linq to xml的世界
本文原始作者博客 http://www.cnblogs.com/toutou Linq 入门篇(一):分分钟带你遨游linq to xml的世界 本文原创来自博客园 请叫我头头哥的博客, 请尊重版权, ...
- 转:OSGi 入门篇:模块层
OSGi 入门篇:模块层 1 什么是模块化 模块层是OSGi框架中最基础的一部分,其中Java的模块化特性在这一层得到了很好的实现.但是这种实现与Java本身现有的一些模块化特性又有明显的不同. 本文 ...
- 转:OSGi 入门篇:生命周期层
OSGi 入门篇:生命周期层 前言 生命周期层在OSGi框架中属于模块层上面的一层,它的运作是建立在模块层的功能之上的.生命周期层一个主要的功能就是让你能够从外部管理应用或者建立能够自我管理的应用(或 ...
随机推荐
- chapter1 events and probability
第一章 事件和概率 1.1 Appication: verifying polynomial identities 1.2 Axioms of probability 1.3 Application ...
- .NET操作Excel高效低内存的开源框架 - MiniExcel
.Net平台上对Excel进行操作主要有两种方式.第一种,把Excel文件看成一个数据库,通过OleDb的方式进行读取与操作:第二种,调用Excel的COM组件.两种方式各有特点. 今天给大家介绍第三 ...
- Http状态码502常见原因及排错思路
Http状态码502常见原因及排错思路 502表示Bad Gateway.当Nginx返回502错误时,通常表示Nginx作为代理服务器无法从上游服务器(如:我们的后端服务器地址)获取有效的响应.导致 ...
- Java Study For Seven Day( 面向对象三)
继承 class Person { String name; int age; } class Student extends Person { void study() { System.out.p ...
- Python之pandas读取Excel
#! -*- coding utf-8 -*- """ 模块功能:读取当前文件夹下的Source里的Excel文件,显示其相关信息 说明:默认把Excel的第一行当做列名 ...
- Mybatis【17】-- Mybatis自关联查询一对多查询
注:代码已托管在GitHub上,地址是:https://github.com/Damaer/Mybatis-Learning ,项目是mybatis-13-oneself-one2many,需要自取, ...
- ZCMU_1117
/相当于看墙,投影之类的东西让我数多少个建筑物/ 解释感觉还不到位,以后再看看 先强调这不是我原创的,只是加了注释.找到原作者后会加链接.以及改变布局 #include <cstdlib> ...
- 移动端NES网页模拟器(1)
前言 移动端浏览器是没有实体键盘的,想要操作游戏就必须为其设置虚拟按键,通过虚拟按键(按钮)的标识与实体键盘的keyCode进行绑定,来达到想要的效果. 这个随笔只封装NES游戏手柄右边的按键,不包含 ...
- 中电金信多模态鉴伪技术抵御AI造假威胁
AI换脸技术,属于深度伪造最常见方式之一,是一种利用人工智能生成逼真的虚假人脸图片或视频的技术.基于深度学习算法,可以将一个人的面部特征映射到另一个人的面部,创造出看似真实的伪造内容.近年来,以A ...
- Java 项目愚蠢的分层及解决方案
<整洁架构之道>的最后一章<细节决定成败>又在讨论 Javaer 永恒的问题:分层后 DAO Service Controller 应该按功能分包还是按层分包. 按功能分包的人 ...