SpringCloud开始的第二课(consul、Feign声明式调用、Jmetter压力测试工具、Hystrix熔断降级兜底、)
一、前提回顾
上文我们讲解了(RestTemplate、Eureka、Eureka集群、Ribbon负载均衡、Eureka节点服务剔除)
上文链接
接下来我们继续讲讲其他的微服务的知识示例
二、Eureka的替换方案
疑问:Eureka那么好用为什么要换掉它呢?
在Euraka的GitHub上,宣布Eureka 2.x闭源。近这意味着如果开发者继续使用作为 2.x 分支上现有工作 repo 一部分发布的代码库和工件,则将自负风险。
那么我们可以替换哪些注册中心呢?(如下)
组件名 | 语言 | CAP | 一致性算法 | 服务健康检查 | 对外暴露接口 |
---|---|---|---|---|---|
Eureka | JAVA | AP(可用性、分区容忍性) | 无 | 可配支持 | HTTP |
Consul | Go | CP(一致性、分区容忍性) | Raft | 支持 | HTTP/DNS |
Zookeeper | JAVA | CP(一致性、分区容忍性) | Paxos | 支持 | 客户端 |
Nacos | JAVA | AP(可用性、分区容忍性) | Raft | 支持 | HTTP |
三、什么是consul
本文我们讲解下consul替代上文的eureka
consul是近几年比较流行的服务发现工具,工作中用到,简单了解一下。consul的三个主要应用场景: 服务发现、服务隔离、服务配置。
Consul 是 HashiCorp 公司推出的开源工具,用于实现分布式系统的服务发现与配置。与其它分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与发现框 架、分布一致性协议实 现、健康检查、Key/Value
存储、多数据中心方案,不再需要依赖其它工具(比如 ZooKeeper 等)。 使用起来也较 为简单。
Consul 使用 Go 语言编写,因此具有天然可移植性(支持Linux、windows和 Mac OS X);安装包仅包含一个可执行文件,方便部署,与 Docker等轻量级容器可无缝配合。
Consul 的优势:
- 使用 Raft 算法来保证一致性, 比复杂的 Paxos 算法更直接. 相比较而言, zookeeper 采用的是Paxos, 而 etcd 使用的则是 Raft。
- 支持多数据中心,内外网的服务采用不同的端口进行监听。 多数据中心集群可以避免单数据中心
的单点故障,而其部署则需要考虑网络延迟, 分片等情况等。 zookeeper 和 etcd 均不提供多数据中心功能的支持。 - 支持健康检查。 etcd 不提供此功能。
- 支持 http 和 dns 协议接口。 zookeeper 的集成较为复杂, etcd 只支持 http 协议。
- 官方提供 web 管理界面, etcd 无此功能。
综合比较, Consul 作为服务注册和配置管理的新星, 比较值得关注和研究。
特性:
- 服务发现
- 健康检查
- Key/Value 存储
- 多数据中心
四、consul与Eureka的区别
(1)一致性
-
Consul强一致性(CP)
- 服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认
为注册成功 - Leader挂掉时,重新选举期间整个consul不可用。保证了强一致性但牺牲了可用性。
- 服务注册相比Eureka会稍慢一些。因为Consul的raft协议要求必须过半数的节点都写入成功才认
-
Eureka保证高可用和最终一致性(AP)
- 服务注册相对要快,因为不需要等注册信息replicate到其他节点,也不保证注册信息是否
replicate成功 - 当数据出现不一致时,虽然A, B上的注册信息不完全相同,但每个Eureka节点依然能够正常对外提供服务,这会出现查询服务信息时如果请求A查不到,但请求B就能查到。如此保证了可用性但牺牲了一致性。
- 服务注册相对要快,因为不需要等注册信息replicate到其他节点,也不保证注册信息是否
(2)开发语言和使用
- eureka就是个servlet程序,跑在servlet容器中
- Consul则是go编写而成,安装启动即可
五、consul的下载与安装
Consul 不同于 Eureka 需要单独安装,访问Consul 官网下载 Consul 的最新版本,我这里是consul1.5.3x。根据不同的系统类型选择不同的安装包。
(注意如果你是阿里云,请开放防火墙端口、安全组,如果有宝塔的话,记得也要开放宝塔的防火墙端口)
linux
## 从官网下载最新版本的Consul服务
wget https://releases.hashicorp.com/consul/1.5.3/consul_1.5.3_linux_amd64.zip
##使用unzip命令解压
unzip consul_1.5.3_linux_amd64.zip
##将解压好的consul可执行命令拷贝到/usr/local/bin目录下
cp consul /usr/local/bin
##测试一下
consul
启动consul服务
0.0.0.0指允许任意ip访问
##已开发者模式快速启动,-client指定客户端可以访问的ip地址
[root@node01 ~]# consul agent -dev -client=0.0.0.0
==> Starting Consul agent...
Version: 'v1.5.3'
Node ID: '49ed9aa0-380b-3772-a0b6-b0c6ad561dc5'
Node name: 'node01'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false,
Auto-Encrypt-TLS: false
启动成功之后访问: http://IP:8500 ,可以看到 Consul 的管理界面
windows
下载解压
- 双击启动
- 打开cmd窗口至该consul.exe文件目录下,运行命令
consul agent -dev -client=0.0.0.0
- 然后访问测试下
六、consul的基本使用
Consul 支持健康检查,并提供了 HTTP 和 DNS 调用的API接口完成服务注册,服务发现,以及K/V存储这些功能。接下来通过发送HTTP请求的形式来了解一下Consul
服务注册与发现
- (1)注册服务
通过postman发送put请求到http://localhost:8500/v1/catalog/register地址可以完成服务注册
{
"Datacenter": "dc1",
"Node": "node01",
"Address": "192.168.74.102",
"Service": {
"ID":"mysql-01",
"Service": "mysql",
"tags": ["master","v1"],
"Address": "192.168.74.102",
"Port": 3306
}
}
-
服务注册成功
-
(2)服务查询
通过postman发送get请求到http://localhost:8500/v1/catalog/services查看所有的服务列表
- 通过postman发送get请求到http://localhost:8500/v1/catalog/service/服务名 查看具体的服务详
情
- (3)服务删除
通过postman发送put请求到http://localhost:8500/v1/catalog/deregister删除服务(注意路径不要结尾加 / )
{
"Datacenter": "dc1",
"Node": "node01",
"ServiceID": "mysql-01"
}
consul的KV存储
可以参照Consul提供的KV存储的API完成基于Consul的数据存储(以下会举例说明)
含义 | 请求路径 | 请求方式 |
---|---|---|
查看key | v1/kv/:key | GET |
保存或更新 | v1/kv/:key | put |
删除key | v1/kv/:key | delete |
-
key值中可以带/, 可以看做是不同的目录结构。
-
value的值经过了base64_encode,获取到数据后base64_decode才能获取到原始值。数据不能大
于512Kb -
不同数据中心的kv存储系统是独立的,使用dc=?参数指定
-
保存key
- 修改指定键值
- 查看key
- 可视化显示
七、基于consul的服务注册
引入依赖
注意:product项目、以及order项目都要引入(需要注册和发现的微服务都要引入)
引入jar包的同时,注释掉上述的eureka的jar包
<!--SpringCloud提供的基于Consul的服务发现-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--actuator用于心跳检查-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
其中 spring-cloud-starter-consul-discovery
是SpringCloud提供的对consul支持的相关依赖。
spring-boot-starter-actuator 适用于完成心跳检测响应的相关依赖。(上文的eureka的安全检测也依赖于这个启动器)
更换配置文件
- 为了保留之前的eureka的配置
配置服务注册
product微服务的yaml文件(注意不需要数据库的,不配置数据库相关的配置)
server:
# 9011 9015
port: 9011 #端口
spring:
application:
name: ebuy-product #服务名称
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/ebuy?useUnicode=true&characterEncoding=utf8
username: root
password: 123
cloud:
consul:
host: localhost
port: 8500
discovery:
register: true
instance-id: ${spring.application.name}-1
service-name: ${spring.application.name}
port: ${server.port}
health-check-path: /actuator/health
health-check-interval: 15s
prefer-ip-address: true
ip-address: ${spring.cloud.client.ip-address}
mybatis:
type-aliases-package: cn.ebuy.product.pojo
mapper-locations: cn/ebuy/product/pojo/*.xml
logging:
level:
cn.ebuy: DEBUG
- 配置consul部分
- 同样order微服务进行配置
- 配置详解
其中 spring.cloud.consul 中添加consul的相关配置 - host:表示Consul的Server的请求地址
- port:表示Consul的Server的端口
- discovery:服务注册与发现的相关配置
- instance-id : 实例的唯一id(推荐必填),spring cloud官网文档的推荐,为了保证生成一
个唯一的id ,也可以换成
- instance-id : 实例的唯一id(推荐必填),spring cloud官网文档的推荐,为了保证生成一
${spring.application.name}:${spring.cloud.client.ipAddress}
- prefer-ip-address:开启ip地址注册
- ip-address:当前微服务的请求ip
启动服务
记得修改server.port,instance-id(前者是端口号,后者是注册的实例名字)
- 启动效果
- 服务展示
- 实例展示
- 调用服务
- 发现之前eureka的配置(负载均衡,服务调用)可以继续使用
八、Feign声明式调用
服务调用Feign入门
前面我们使用的RestTemplate实现REST API调用,代码大致如下:
@GetMapping("/ribbon/{id}")
public EasybuyProduct getOrderByRibbonId(@PathVariable long id){
return restTemplate.getForObject("http://ebuy-product/product/"+id,EasybuyProduct.class);
}
那么为什么RestTemplate用着好好的,为什么要用Feign呢?
由代码可知,我们是使用拼接字符串的方式构造URL的,该URL只有一个参数。
但是,在现实中,URL中往往含有多个参数。
这时候我们如果还用这种方式构造URL,那么就会非常痛苦。那应该如何解决? 我们带着这样的问题进入到本章的学习
Feign简介
Feign是Netflix开发的声明式,模板化的HTTP客户端,其灵感来自Retrofit,JAXRS-2.0以及WebSocket.
- Feign可帮助我们更加便捷,优雅的调用HTTP API。
- 在SpringCloud中,使用Feign非常简单——创建一个接口,并在接口上添加一些注解,代码就完成了。
- Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
- SpringCloud对Feign进行了增强,使Feign支持了SpringMVC注解,并整合了Ribbon和Eureka,
从而让Feign的使用更加方便。
基于Feign的服务调用
引入依赖
只需要在服务调用方添加即可!
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
启动类添加Feign的支持
启动类激活FeignClient
创建一个Feign接口,此接口是在Feign中调用微服务的核心接口
在服务消费者ebuy_order 添加一个 OrderFeginClient 接口
- 就是服务注册方的controller方法
- 做个对比
之前的restTemplate负载均衡的调用
- 大体是相似的
修改调用controller
重启服务
重启服务,调用
- 测试正常使用,并且负载均衡正常使用
Feign和Ribbon的联系
Ribbon是一个基于 HTTP 和 TCP 客户端 的负载均衡的工具。它可以 在客户端
配置RibbonServerList(服务端列表),使用 HttpClient 或 RestTemplate
模拟http请求,步骤相当繁琐。
Feign 是在 Ribbon的基础上进行了一次改进,是一个使用起来更加方便的 HTTP 客户端。采用接口的方式,只需要创建一个接口,然后在上面添加注解即可 ,将需要调用的其他服务的方法定义成抽象方 法即可,不需要自己构建http请求。然后就像是调用自身工程的方法调用,而感觉不到是调用远程方法,使得编写客户端变得非常容易。
负载均衡
Feign中本身已经集成了Ribbon依赖和自动配置,因此我们不需要额外引入依赖,也不需要再注册
RestTemplate 对象。另外,我们可以像之前说的那样去配置Ribbon,可以通过 ribbon.xx 来进
行全局配置。也可以通过 服务名.ribbon.xx 来对指定服务配置:
并且不依赖于之前的注解
- 仍然是负载均衡!!!
九、Feign的配置
为什么要配置Feign,之前用的不是好好的吗?,要怎么配置?
因为真实的请求环境并不总是一帆风顺,可能会网络阻塞、可能能会线程拥挤,导致feign调用的服务不能及时的完成服务的正常使用,导致报错(接下来来个例子演示下)
- 修改服务提供者的controller
- 重启服务
- 请求服务
报错(读取超时时间 超时)
- 配置方法一如下
代码:
ebuy-product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 随机,默认轮询
ConnectTimeout: 2500 # Ribbon的连接超时时间(创建连接时间:毫秒)
ReadTimeout: 5000 # Ribbon的数据读取超时时间 (得到数据的时间)
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数 (1表示不重试自己)
- 配置方法二 如下:
从Spring Cloud Edgware开始,Feign支持使用属性自定义Feign。对于一个指定名称的Feign Client(例如该Feign Client的名称为 feignName ),Feign支持如下配置项:
代码:
feign:
client:
config:
ebuy-product:
connectTimeout: 5000 # 相当于Request.Options
readTimeout: 5000 # 相当于Request.Options
# 配置Feign的日志级别,相当于代码配置方式中的Logger
loggerLevel: full
-
connectTimeout : 建立链接的超时时长
-
readTimeout : 读取超时时长
-
loggerLevel: Fegin的日志级别
-
errorDecoder :Feign的错误解码器
-
retryer : 配置重试
-
requestInterceptors : 添加请求拦截器
-
decode404 : 配置熔断不处理404异常
-
再次请求
-
虽然是慢了点,但是数据正常返回,服务正常!!!
请求压缩
Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数即可开启请求与响应的压缩功能:
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩
同时,我们也可以对请求的数据类型,以及触发压缩的大小下限进行设置:
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
注:上面的数据类型、压缩大小下限均为默认值。
日志级别
在开发或者运行阶段往往希望看到Feign请求过程的日志记录,默认情况下Feign的日志是没有开启的。
要想用属性配置方式来达到日志效果,只需在 application.yml 中添加如下内容即可:
feign:
client:
config:
order-product:
loggerLevel: FULL
logging:
level:
cn.warehouse.order.fegin.ProductFeginClient:
debug
- logging.level.xx : debug : Feign日志只会对日志级别为debug的做出响应
- feign.client.config.shop-service-product.loggerLevel : 配置Feign的日志Feign有四种
日志级别:- NONE【性能最佳,适用于生产】:不记录任何日志(默认值)
- BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间
- HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
- FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数
据。
十、Jmetter压力测试工具
Jmetter安装十分简单,下载解压之后,安装目录下
bin/jmeter.bat 已管理员身份启动即可
改造项目
改造order调用服务方的controller
上图可以看出getMsg这个方法是不调用product模块的服务的!
- 接下来修改tomcat的线程数
模拟洪峰环境(线程不足用户使用)
- 然后重启服务
配置测试工具
启动测试
这显然是不好的用户体验
十一、系统负载过高存在的问题
问题分析
在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务累计,导致服务瘫痪。
在SpringBoot程序中,默认使用内置tomcat作为web服务器。单tomcat支持最大的并发请求是有限的,如果某一接口阻塞,待执行的任务积压越来越多,那么势必会影响其他接口的调用。
上述的测试便是order调用product的服务出现问题,导致任务累计,进而使得order的tomcat的线程处于阻塞状态,getMsg的请求被排队。
那么如何解决上述的问题呢?
线程池的形式实现服务隔离
实现的主要思路是将上述的order调用product的服务的线程进行隔离,与getMsg方法不处在同一线程池中,进而使得getMsg方法正常执行,但是order调用product的服务仍然会很拥塞(但是可以返回fallback,结束线程)!
引入jar包
<!--线程隔离-->
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.12</version>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-javanica</artifactId>
<version>1.5.12</version>
</dependency>
十二、服务熔断断Hystrix
服务容错的核心知识
雪崩效应
在微服务架构中,一个请求需要调用多个服务是非常常见的。如客户端访问A服务,而A服务需要调用B
服务,B服务需要调用C服务,由于网络原因或者自身的原因,如果B服务或者C服务不能及时响应,A服
务将处于阻塞状态,直到B服务C服务响应。此时若有大量的请求涌入,容器的线程资源会被消耗完毕,
导致服务瘫痪。服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难 性的严重后果,这就是服务故障的“雪崩”效应。
雪崩是系统中的蝴蝶效应导致其发生的原因多种多样,有不合理的容量设计,或者是高并发下某一个方
法响应变慢,亦或是某台机器的资源耗尽。从源头上我们无法完全杜绝雪崩源头的发生,但是雪崩的根
本原因来源于服务之间的强依赖,所以我们可以提前评估,做好熔断,隔离,限流。
服务隔离
顾名思义,它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。
当有故障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体 的系统服务
熔断降级
熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压
力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。这 种牺牲局部,保全整体的措施就叫做熔断
所谓降级,就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的
fallback回调,返回一个缺省值。 也可以理解为兜底
服务限流
限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量已达到保护系统的目的。一般来说
系统的吞吐量是可以被测算的,为了保证系统的稳固运行,一旦达到的需要限制的阈值,就需要限制流
量并采取少量措施以完成限制流量的目的。比方:推迟解决,拒绝解决,或者者部分拒绝解决等等。
Hystrix介绍
Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止级联失
败,从而提升系统的可用性与容错性。Hystrix主要通过以下几点实现延迟和容错。
- 包裹请求:使用HystrixCommand包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用
了设计模式中的“命令模式”。 - 跳闸机制:当某服务的错误率超过一定的阈值时,Hystrix可以自动或手动跳闸,停止请求该服务
一段时间。 - 资源隔离:Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程池已满,
发往该依赖的请求就被立即拒绝,而不是排队等待,从而加速失败判定。 - 监控:Hystrix可以近乎实时地监控运行指标和配置的变化,例如成功、失败、超时、以及被拒绝
的请求等。 - 回退机制:当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑由开发人员
自行提供,例如返回一个缺省值。 - 自我修复:断路器打开一段时间后,会自动进入“半开”状态。
restTemplate实现服务熔断
引入jar包
<!--熔断-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
因为要用到restTemplate的熔断降级,记得将之前注释掉的负载均衡注解去除
开启熔断
在启动类 OrderApplication 中添加 @EnableCircuitBreaker 注解开启对熔断器的支持。
修改项目(局部熔断处理)
解读
由代码可知,为 hystrixFindById 方法编写一个回退方法orderFallBack,该方法与 hystrixFindById 方法具有相同的参数与返回值类型,该方法返回一个默认的错误信息。 在 hystrixFindById 方法上,使用注解
@HystrixCommand
的fallbackMethod属性,指定熔断触发的降级方法 是
orderFallBack。 因为熔断的降级逻辑方法必须跟正常逻辑方法保证:相同的参数列表和返回值声明。 在
hystrixFindById 方法上 HystrixCommand(fallbackMethod = “orderFallBack”) 用来 声明一个降级逻辑的方法 当ebuy-product 微服务正常时,浏览器访问
http://localhost:9016/order/hystrix/816753
重启项目
直接请求 测试
这是因为之前在product服务提供方那里加了个线程休眠为2秒,而hystrix判断服务超过1秒未返回,就进行熔断降级处理!!
修改配置文件
因为我们在product那里设置了休眠2秒,来模拟并发问题。
请求在超过1秒后都会返回错误信息,这是因为Hystix的默认超时时长为1,我们可以通过配置修改这个值:
再次请求
- 重启项目,再次请求
- 未被熔断降级处理,因为请求处理时长小于3秒
停止product提供者服务
当将商品微服务停止时继续访问
此时Hystrix配置已经生效进入熔断降级方法。
全局熔断处理
上述的熔断处理已经实现,但是如果每一个请求都要配置一个对应的熔断的兜底方法,那肯定是不行的!!!所以hystrix提供了一种全局的熔断处理。
- 新建一个controller,与之前的controller作区分
package cn.ebuy.order.controller;
import cn.ebuy.order.pojo.EasybuyProduct;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/order2")
@DefaultProperties(defaultFallback = "orderFallBack")
public class Order2Controller {
@Autowired
RestTemplate restTemplate;
@GetMapping("/testString")
public String testString(){
return "测试成功";
}
@RequestMapping(value = "/hystrix/{id}")
@HystrixCommand
public EasybuyProduct hystrixFindById(@PathVariable Long id){
EasybuyProduct easybuyProduct=restTemplate.getForObject("http://ebuy-product/product/"+id,EasybuyProduct.class);
return easybuyProduct;
}
/**
* 降级(兜底)
* @return
*/
/*注意全局的不要加参数*/
public EasybuyProduct orderFallBack(){
EasybuyProduct easybuyProduct=new EasybuyProduct();
easybuyProduct.setEpDescription("全局熔断处理");
return easybuyProduct;
}
}
注意此时兜底的这个orderFallBack方法参数可以为空,但是返回类型必须要和加了@HystrixCommand
的方法保持一致,后期我们将写一个包装类(涵盖实体泛型对象、以及一些基本信息),用来作为熔断降级的返回类型,这里暂不做演示
重启服务
重启服务
服务正常提供
服务停止提供
熔断降级处理
上述我们实现了restTemplate的熔断降级,接下来实现Feign的熔断降级!!!
Feign熔断降级
引入jar包
SpringCloud Fegin默认已为Feign整合了hystrix,所以添加Feign依赖后就不用在添加hystrix,那么怎么才能让Feign的熔断机制生效呢,只要按以下步骤开发:
启动类加注解
如果restTemplate的熔断降级已经配置了的话,那么这一步省略
//开启熔断
@EnableCircuitBreaker
修改配置文件
feign:
hystrix: #在feign中开启hystrix熔断
enabled: true
新建一个Feign熔断的类(组件)
package cn.ebuy.order.feign;
import cn.ebuy.order.pojo.EasybuyProduct;
import org.springframework.stereotype.Component;
//注意要加载该组件
@Component
public class OrderFeignClientCallBack implements OrderFeignClient {
@Override
public EasybuyProduct findById(Long id) {
EasybuyProduct easybuyProduct=new EasybuyProduct();
easybuyProduct.setEpDescription("Feign熔断处理");
return easybuyProduct;
}
}
修改之前的Feign接口
重启服务
product服务正常提供
停止product服务
这样Feign的熔断降级便是完成了。