Hystrix的使用4和OpenFeign结合使用
Hystrix的使用4-和OpenFeign结合使用
1.简介
OpenFeign中已经集成了Hystrix,不用再引入Hystrix依赖。
2.代码实现
2.1 父工程POM文件
<packaging>pom</packaging> <modules>
<!-- 公共工程,请看我的github -->
<module>cloud-api-commons</module>
<!-- Eureka注册中心 -->
<module>cloud-eureka-server7001</module>
<!-- 服务提供者 -->
<module>cloud-provider-payment-hystrix8001</module>
<!-- 服务消费者 -->
<module>cloud-consumer-order-hystrix80</module>
</modules>
<!-- 统一管理jar包版本 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
<spring.boot.version>2.2.2.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR1</spring.cloud.version>
<hutool-all.version>5.1.0</hutool-all.version>
<liuhangs.cloud.api.version>1.0.0-SNAPSHOT</liuhangs.cloud.api.version>
</properties>
<distributionManagement>
<site>
<id>website</id>
<url>scp://webhost.company.com/www/website</url>
</site>
</distributionManagement>
<!-- 子模块继承之后,提供作用:锁定版本 + 子module不用谢groupId和version -->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
2.2 服务提供者cloud-provider-payment-hystrix8001
2.2.1 服务提供者POM文件
因为我们不在服务提供者代码里测试Hystrix,所以不用引入Hystrix依赖。
<dependencies> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.liuhangs.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${liuhangs.cloud.api.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.2.2 服务提供者application.yml
server: port: 8001
spring:
application:
name: cloud-provider-payment-hystrix
eureka:
client:
#是否注册到eureka
register-with-eureka: true
# 是否在本地缓存注册表信息
fetch-registry: true
service-url:
# 配置eureka的地址,如果多台则逗号分隔。
defaultZone: http://eureka7001.com:7001/eureka
2.2.3 服务提供者service
service接口:
import com.liuhangs.springcloud.api.entities.CommonResult;/**payment服务接口
*/
public interface PaymentHystrixService {
/**
* 正常方法
* @param id
* @return
*/
public CommonResult getPaymentOK(Long id);
/**
* 给80服务消费者准备的超时方法,避免和前面的服务降级方法混淆
*/
public CommonResult getPaymentTimeOutFor80(Long id);
}
service实现类:
import com.liuhangs.springcloud.api.entities.CommonResult;import com.liuhangs.springcloud.payment.service.PaymentHystrixService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
/**这个类里一个需要5秒才能返回值的接口 */
@Service
@Slf4j
public class PaymentHystrixServiceImpl implements PaymentHystrixService {
@Value("${server.port}")
private String SERVER_PORT;
@Override
public CommonResult getPaymentOK(Long id)
{
return new CommonResult(200, "请求ID为:" + id + ", 当前线程是:" + Thread.currentThread().getName() +
"," +
" " +
"服务端口:" +
SERVER_PORT);
}
/**
* 给80服务消费者准备的超时方法,避免和前面的服务降级方法混淆
* 此方法会睡眠5秒
* @param id
* @return
*/
@Override
public CommonResult getPaymentTimeOutFor80(Long id)
{
try
{
TimeUnit.MILLISECONDS.sleep(5000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return new CommonResult(200, "请求ID为:" + id + ", 当前线程是:" + Thread.currentThread().getName() + ", 服务端口:" +
SERVER_PORT + ", 线程睡眠5秒");
}
}
2.2.4 服务提供者controller
import com.liuhangs.springcloud.api.entities.CommonResult;import com.liuhangs.springcloud.api.entities.Payment;
import com.liuhangs.springcloud.payment.service.PaymentHystrixService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**服务提供者对外提供的接口
*/
@RequestMapping("provider/payment/hystrix")
@RestController
public class PaymentHystrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
@GetMapping("/ok/{id}")
public CommonResult getPaymentOK(@PathVariable("id") Long id)
{
return paymentHystrixService.getPaymentOK(id);
}
/**
* 给80服务消费者准备的超时接口
* @param id
* @return
*/
@GetMapping("/timeoutfor80/{id}")
public CommonResult getPaymentTimeOutFor80(@PathVariable("id") Long id)
{
return paymentHystrixService.getPaymentTimeOutFor80(id);
}
}
2.2.4 服务提供者启动类
/**服务提供者启动类 */
@SpringBootApplication
public class PaymentHystrixStart8001 {
public static void main(String[] args)
{
SpringApplication.run(PaymentHystrixStart8001.class, args);
}
}
2.3 Eureka注册中心cloud-eureka-server7001
2.3.1 注册中心POM文件
<dependencies> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>com.liuhangs.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${liuhangs.cloud.api.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.3.2 注册中心application.yml
server: port: 7001
spring:
application:
name: cloud-eureka-server
eureka:
instance:
hostname: eureka7001.com
client:
# 是否将当前服务注册到eureka
registerWithEureka: false
# 是否在本地缓存注册表信息,默认为true
fetchRegistry: true
serviceUrl:
# 配置自己就是单机,配置其他eureka的地址就是集群,如果多台则逗号分隔。
defaultZone: http://eureka7001.com:7001/eureka
2.3.3 注册中心启动类
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
/**注册中心启动类
*/
@SpringBootApplication
@EnableEurekaServer
public class EurekaStart7001 {
public static void main(String[] args)
{
SpringApplication.run(EurekaStart7001.class, args);
}
}
2.4 服务消费者cloud-consumer-order-hystrix80
2.4.1 服务消费者POM文件
<dependencies> <!-- OpenFeign中已经集成了Hystrix,不用再引入Hystrix依赖。 -->
<!-- <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.liuhangs.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${liuhangs.cloud.api.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.4.2 服务消费者application.yml
需要注意:
- OpenFeign的超时调用时间需要调大(默认为1秒),否则看不到服务降级的效果。通过
ribbon.ReadTimeout
和ribbon.ConnectTimeout
设置。 - 服务提供者需要通过
feign.hystrix.enabled
开启Hystrix降级处理。 - 可以通过
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
设置超时降级时间(Hystrix默认一秒)。
server: port: 80
eureka:
client:
#是否注册到eureka
register-with-eureka: true
# 是否在本地缓存注册表信息
fetch-registry: true
service-url:
# 配置eureka的地址,如果多台则逗号分隔。
defaultZone: http://eureka7001.com:7001/eureka
#需要将接口超时的时间调大(默认1秒),否则在调用服务消费者时会直接报超时异常。
ribbon:
#调用接口读取超时时间
ReadTimeout: 6000
#调用接口连接超时时间
ConnectTimeout: 2000
#开启Hystrix降级处理
feign:
hystrix:
enabled: true #在Feign中开启Hystrix。如果处理自身的容错就开启。开启方式与生产端不一样。
#设置超时降级时间(spring-cloud-starter-openfeign中的HystrixCommandProperties默认为1000毫秒)
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000
#设置hystrix日志级别是DEBUG
logging:
level:
com.netflix.hystrix: DEBUG
2.4.3 服务消费者service接口
这里是使用的OpenFeign,所以需要使用接口,并且在接口上加上OpenFeign客户端注解@FeignClient
。
加上需要使用Hystrix进行服务降级,所以在@FeignClient
注解中配置fallback属性,配置统一的服务降级处理类。这里配置的服务降级处理类为PaymentHystrixFallBackService。
import com.liuhangs.springcloud.api.entities.CommonResult;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;
/**fallback属性为统一的服务降级处理类
*/
@FeignClient(name="CLOUD-PROVIDER-PAYMENT-HYSTRIX", fallback = PaymentHystrixFallBackService.class)
@Service
public interface PaymentHystrixService {
@GetMapping("provider/payment/hystrix/ok/{id}")
public CommonResult getPaymentOK(@PathVariable("id") Long id);
/**
* 调用服务提供者的getPaymentTimeOutFor80接口
* @param id
* @return
*/
@GetMapping("provider/payment/hystrix/timeoutfor80/{id}")
public CommonResult getPaymentTimeOutFor80(@PathVariable("id") Long id);
}
2.4.4 服务消费者统一的服务降级处理类
注意:服务降级处理类需要实现OpenFeign客户端调用类PaymentHystrixService。
/**PaymentHystrixService类对应的服务降级处理类 * 这个类要实现调用服务消费的OpenFeign接口PaymentHystrixService
*/
@Service
public class PaymentHystrixFallBackService implements PaymentHystrixService {
@Override
public CommonResult getPaymentOK(Long id)
{
return new CommonResult(200, "使用id:" + id
+"调用PaymentHystrixService服务的getPaymentOK方法失败,进入降级处理方法getPaymentOK");
}
@Override
public CommonResult getPaymentTimeOutFor80(Long id)
{
return new CommonResult(200, "使用id:" + id
+"调用PaymentHystrixService服务的getPaymentTimeOut方法失败,进入降级处理方法getPaymentTimeOutFor80");
}
}
2.4.5 服务消费者controller
import com.liuhangs.springcloud.api.entities.CommonResult;import com.liuhangs.springcloud.order.service.PaymentHystrixService;
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;
/**服务消费者对外提供的接口
*/
@RequestMapping("/consumer/order/hystrix")
@RestController
public class OrderHystrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
@GetMapping("/ok/{id}")
public CommonResult getPaymentOK(@PathVariable("id") Long id) {
return paymentHystrixService.getPaymentOK(id);
}
@GetMapping("/timeout/{id}")
public CommonResult getPaymentTimeOut(@PathVariable("id") Long id) {
return paymentHystrixService.getPaymentTimeOutFor80(id);
}
}
2.4.6 服务消费者启动类
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**服务消费者启动类
*/
@SpringBootApplication
@EnableFeignClients //开启OpenFeign
public class OrderHystrixStart80 {
public static void main(String[] args)
{
SpringApplication.run(OrderHystrixStart80.class, args);
}
}
2.5 测试
启动Eureka、服务提供者、服务消费者。
2.5.1 调用正常返回的方法
浏览器访问:http://localhost/consumer/order/hystrix/ok/1 ,返回如下:
2.5.2 调用超时降级方法
浏览器访问:http://localhost/consumer/order/hystrix/timeout/1 ,返回如下:
3.代码请见
https://github.com/ainydexiaohai/cloud2020
4.参考文章
- 尚硅谷SpringCloud培训课程
以上是 Hystrix的使用4和OpenFeign结合使用 的全部内容, 来源链接: utcz.com/z/518491.html