8.5 客户端服务降级
- 通常情况下,我们都会在客户端进行服务降级,当客户端调用的服务端的服务不可用时,客户端直接进行服务降级处理,避免其线程被长时间、不必要地占用。
- 沿用microservice-cloud-consumer-dept-openFeign客户端工程,在pom.xml 中添加 Hystrix 的依赖,代码如下。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<!--引入父工程pom-->
<parent>
<artifactId>spring-cloud-microservice</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>microservice-cloud-consumer-dept-openFeign</artifactId>
<!--实体类API+web-->
<dependencies>
<!--引入公共子模块-->
<dependency>
<groupId>org.example</groupId>
<artifactId>microservice-cloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--devtools 开发工具 这个热部署重启得更快-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--logback -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--springboot-test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--jetty-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
<!--日志-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<!--Spring Cloud Eureka 客户端依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.3</version>
</dependency>
<!--Spring Cloud Ribbon 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
<version>2.7.18</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-ribbon</artifactId>
<version>2.2.10.RELEASE</version>
<scope>compile</scope>
</dependency>
<!--hystrix 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
- 在 microservice-cloud-consumer-dept-openFeign 的 application.yml 中添加以下配置,开启客户端的 Hystrix 功能。
feign:
circuitbreaker:
enabled: true
- 在 com.example.service包下,创建一个名为 DeptHystrixService 的服务绑定接口,与 microservice-cloud-provider-dept-hystrix-8004中提供的服务接口进行绑定,代码如下。
package com.example.service;
import com.example.config.FeignConfiguration;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@Service
@FeignClient(value = "MICROSERVICECLOUDPROVIDERDEPTHYSTRIX",configuration = FeignConfiguration.class)
public interface DeptHystrixService {
@GetMapping("/dept/getInfo/Hystrix/200/{id}")
String dept_200(@PathVariable("id") Integer id);
@GetMapping("/dept/testTimeOut/Hystrix/{id}")
String testTimeOut(@PathVariable("id") Integer id);
}
- 在 com.example.controller 包下创建一个名为 DeptHystrixController的 Controller ,注意超时提示要与服务端进行区分,方便测试。代码如下。
package com.example.controller;
import com.example.service.DeptHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
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.RestController;
@RestController
@Slf4j
public class DeptHystrixController {
@Autowired
private DeptHystrixService deptHystrixService;
@GetMapping("/consumer/dept/getInfo/Hystrix/200/{id}")
public String dept_200(@PathVariable("id") Integer id) {
String info = deptHystrixService.dept_200(id);
log.info(info);
return "客户端请求"+info;
}
//在客户端进行降级
//超时测试,该服务的响应时间为 3 秒
@GetMapping("/consumer/dept/testTimeOut/Hystrix/{id}")
@HystrixCommand(fallbackMethod = "deptTimeoutHandler")
public String testTimeOut(@PathVariable("id") Integer id){
String info = deptHystrixService.testTimeOut(id);
//当Application.yml中没有配置当前端口号,只能使用此方式获取端口
log.info(info);
return info;
}
// testTimeOut方法的 专用 fallback 方法
public String deptTimeoutHandler(Integer id){
log.info("testTimeOut 出错,服务被降级!");
return "因当前请求testTimeOut超时,客户端服务降级,返回提示信息!当前线程:"+Thread.currentThread().getName()+"请求超时500。ID+"+id;
}
}
- 在配置文件 appliction.yml 中添加以下配置,在客户端配置ribbon和hystrix全局和特定方法请求超时的时间。
spring:
application:
name: feignServer
server:
port: 80
servlet:
context-path: /
#Jetty specific properties
jetty:
threads:
acceptors: -1 #Number of acceptor threads to use. When the value is -1, the default, the number of acceptors is derived from the operating environment.
selectors: -1 #Number of selector threads to use. When the value is -1, the default, thenumber of selectors is derived from the operating environment.
max-http-form-post-size: 200000 #Maximum size of the form content in any HTTP post request.
eureka:
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: true #指示此客户端是否应从 eureka 服务器获取 eureka 注册表信息
service-url: #监控页面地址
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #发布的服务注册中心地址,单机
defaultZone: http://eurekaserver7001.com:7001/eureka/,http://eurekaserver7002.com:7002/eureka/,http://eurekaserver7003.com:7003/eureka/ #集群版 将当前的 Eureka Server 注册到 7003 和 7003 上,形成一组互相注册的 Eureka Server 集群
feign:
client:
config:
## default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间
feignServer: #feignServer这个服务单独配置超时时间
connectTimeout: 6000
readTimeout: 6000
circuitbreaker:
enabled: true
ribbon:
eager-load:
enabled: true #关闭懒加载
# 指的是建立连接后从服务器读取到可用资源所用的时间
ReadTimeout: 6000
# 指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间
ConnectTimeout: 6000
eureka:
enabled: false #禁用Eureka
logging:
level:
com:
example:
service: debug
MICROSERVICECLOUDPROVIDERDEPT:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 7000 #配置请求超时时间
DeptHystrixService#testTimeOut(Integer):
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 #配置具体方法超时时间 为 3 秒
- 在配置文件中设计请求的超时时间时,需要注意以下 2 点:
-
- Hystrix 可以来为所有请求(方法)设置超时时间(单位为毫秒),若请求超时则触发全局的回退方法进行处理。
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=mmm
-
- Hystrix 还可以为某个特定的服务请求(方法)设置超时时间,格式如下:
hystrix.command.xxx#yyy(zzz).execution.isolation.thread.timeoutInMilliseconds=mmm
格式说明如下:
- xxx:为包含该服务方法的类的名称(通常为服务绑定接口的名称),例如 DeptHystrixService 接口。
- yyy:服务方法名,例如 testTimeOut 方法。
- zzz:方法内的参数类型,例如 Integer、String 等等
- mmm:要设置的超时时间,单位为毫秒(1 秒 =1000 毫秒)
- 在 microservice-cloud-consumer-dept-openFeign 的主启动类上,使用 @EnableHystrix 注解开启客户端 Hystrix 功能,代码如下。
package com.example;
import com.example.config.FeignConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.cloud.openfeign.EnableFeignClients;
//OpenFeign和Eureka整合以后,容户端可以直接调用用,不用关心服务的IP地址和端口号
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //开启 OpenFeign 功能
// 如果只有一个服务就可以直接使用@RibbonClient注解,而不需要@RibbonClients。
// name是写服务提供方的服务名 configuration是指定我们上面创建的配置类
@RibbonClients(value = {
@RibbonClient(name = "MICROSERVICECLOUDPROVIDERDEPT",configuration = FeignConfiguration.class)
})
//@RibbonClient(name = "MICROSERVICECLOUDPROVIDERDEPT",configuration = FeignConfiguration.class)
@EnableHystrix //启用 Hystrix
public class MicroserviceCloudConsumerDeptOpenFeignApplication {
public static void main(String[] args) {
SpringApplication.run(MicroserviceCloudConsumerDeptOpenFeignApplication.class, args);
}
}
- 测试前提是保证服务端请求正常不被降级。所以要修改 microservice-cloud-provider-dept-hystrix-8004 中 DeptServiceImpl的代码,将 dept_timeout_500() 方法的运行时间修改为 4 秒(小于超时时间 5 秒),以,代码如下。
//一旦该方法失败并抛出了异常信息后,会自动调用 @HystrixCommand 注解标注的 fallbackMethod 指定的方法
@HystrixCommand(fallbackMethod = "dept_timeout_handler",
规定 5 秒钟以内就不报错,正常运行,超过 5 秒就报错,调用指定的方法
commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")})
@Override
public String dept_timeout_500(Integer id) {
try {
//Thread.sleep(6000);
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "服务端当前线程:"+Thread.currentThread().getName()+"请求超时500。ID+"+id;
}
// 当服务出现故障后,调用该方法给出友好提示
public String dept_timeout_handler(Integer id){
return "服务端因当前请求超时,服务降级,返回提示信息!当前线程:"+Thread.currentThread().getName()+"请求超时500。ID+"+id;
}
- 先测试下服务端dept_timeout_500() 方法是否被降级,重启 microservice-cloud-provider-dept-hystrix-8004 和 microservice-cloud-consumer-dept-openFeign,使用浏览器访问,访问http://127.0.0.1:8004/dept/testTimeOut/Hystrix/1
- 使用浏览器访问“http://localhost/consumer/dept/testTimeOut/Hystrix/1”,结果如下图。
- 修改microservice-cloud-consumer-dept-openFeign的application.yml,将超时方法请求时间改为5 秒
DeptHystrixService#testTimeOut(Integer):
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 #配置具体方法超时时间 为 5 秒
-
重启 microservice-cloud-consumer-dept-openFeign,使用浏览器访问,访问http://localhost/consumer/dept/testTimeOut/Hystrix/1
-
由此可见可以正常访问dept_timeout_500方法内的数据,请求并未超时。
下一篇:SpringCloud-21-Hystrix全局降级和解耦降级逻辑
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/123807.html