SpringCloud 实战十四:Hystrix服务降级

  作者:记性不好的阁主

cloud-provider-hystrix-payment8001服务模块


1、引入依赖


<?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">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.laoxu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-provider-hystrix-payment8001</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
<dependency>
<groupId>com.laoxu.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

</project>


2、配置端口


server:
port: 8001
spring:
application:
name: cloud-provier-hystrix-payment

eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defualtZone: http://eureka7001.com:7001/eureka



3、创建启动类


package com.laoxu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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


4、业务层


package com.laoxu.springcloud.service;

import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {

//正常访问返回ok的方法
public String paymentInfo_OK(Integer id){
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_OK, id:" + id + "\t" + "哈哈";
}

public String paymentInfo_Timeout(Integer id){
long second = 3;
try {
TimeUnit.SECONDS.sleep(second);
}catch (InterruptedException e){
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "哈哈" + "耗时" +second+"秒钟";
}

}



package com.laoxu.springcloud.controller;

import com.laoxu.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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 PaymentController {

@Autowired
private PaymentService paymentService;

@Value("${server.port}")
private String serverPort;

@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id){
String result = paymentService.paymentInfo_OK(id);
log.info("******result: " + result);
return result;
}


@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id") Integer id){
String result = paymentService.paymentInfo_Timeout(id);
log.info("******result: " + result);
return result;
}

}





5、启动服务




6、测试

访问 http://localhost:8001/payment/hystrix/ok/31



访问 http://localhost:8001/payment/hystrix/timeout/31




cloud-consumer-feign-hystrix-order80服务模块



1、引入依赖


<?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">
<parent>
<artifactId>cloud2020</artifactId>
<groupId>com.laoxu.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>cloud-consumer-feign-hystrix-order80</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
<dependency>
<groupId>com.laoxu.springcloud</groupId>
<artifactId>cloud-api-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

</project>


2、配置端口



server:
port: 80
spring:
application:
name: cloud-consumer-feign-hystrix-order

eureka:
client:
# 将自己注册进eureka中心
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka, http://eureka7002.com:7002/eureka



3、创建启动类


package com.laoxu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

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


4、创建控制器


package com.laoxu.springcloud.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixService {

@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id);

@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id") Integer id);
}



package com.laoxu.springcloud.controller;

import com.laoxu.springcloud.service.PaymentHystrixService;
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 OrderHystrixController {

@Autowired
private PaymentHystrixService paymentHystrixService;

@GetMapping("/consumer/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id){
String result = paymentHystrixService.paymentInfo_OK(id);
return result;

}


@GetMapping("/consumer/payment/hystrix/timeout/{id}")
public String paymentInfo_Timeout(@PathVariable("id") Integer id){
String result = paymentHystrixService.paymentInfo_Timeout(id);
return result;
}

}



5、测试


访问:http://localhost/consumer/payment/hystrix/ok/31 成功




访问:http://localhost/consumer/payment/hystrix/timeout/31 超时






解决方案:服务降级


相当于:try{  当前服务  }catch{  降级服务  }


  • 修改服务提供者模块:cloud-provider-hystrix-payment


原服务层:


package com.laoxu.springcloud.service;

import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {

//正常访问返回ok的方法
public String paymentInfo_OK(Integer id){
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_OK, id:" + id + "\t" + "哈哈";
}

public String paymentInfo_Timeout(Integer id){
long second = 3;
try {
TimeUnit.SECONDS.sleep(second);
}catch (InterruptedException e){
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "哈哈" + "耗时" +second+"秒钟";
}

}


添加降级服务:


package com.laoxu.springcloud.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {

//正常访问返回ok的方法
public String paymentInfo_OK(Integer id){
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_OK, id:" + id + "\t" + "哈哈";
}

@HystrixCommand(fallbackMethod = "paymentInfo_TimeoutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})
public String paymentInfo_Timeout(Integer id){
long second = 3;
try {
TimeUnit.SECONDS.sleep(second);
}catch (InterruptedException e){
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "哈哈" + "耗时" +second+"秒钟";
}

public String paymentInfo_TimeoutHandler(Integer id){
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "系统繁忙!请稍后再试!!";
}


}




@HystrixCommand 指定降级服务
@HystrixProperty 指定超时时间,这里表示等待2秒后则会直接调用降级服务(paymentInfo_TimeoutHandler)并返回


  • 在启动类添加注解开启服务降级


package com.laoxu.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

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


  • 重启服务:cloud-provider-hystrix-payment





调用降级服务:





  • 测试运行异常


  • 修改代码,故意制造运行异常


package com.laoxu.springcloud.service;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
public class PaymentService {

//正常访问返回ok的方法
public String paymentInfo_OK(Integer id){
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_OK, id:" + id + "\t" + "哈哈";
}

@HystrixCommand(fallbackMethod = "paymentInfo_TimeoutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})
public String paymentInfo_Timeout(Integer id){
// long second = 3;
// try {
// TimeUnit.SECONDS.sleep(second);
// }catch (InterruptedException e){
// e.printStackTrace();
// }
int age = 10/0;
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "哈哈";
}

public String paymentInfo_TimeoutHandler(Integer id){
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "系统繁忙!请稍后再试!!";
}


}




调用降级服务:




一般服务降级放在消费者,这里服务降级是放在服务提供者。


-----------------------------------------------------------------


全局服务降级方法


  1. 添加全局fallback方法:payment_Globle_FallbackMethod
  2. 添加全局注解指定默认降级方法@DefaultProperties(defaultFallback = "payment_Globle_FallbackMethod")
  3. 在需要服务降级的接口上方添加注解@HystrixCommand即可启动服务降级
  4. paymentInfo_Timeout方法已经指定了特定的服务降级,那么只会调用特定的服务降级方法,不会调用默认的服务降级方法
  5. 全局服务降级避免了代码膨胀,合理的减少了代码量


修改服务层:


package com.laoxu.springcloud.service;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@DefaultProperties(defaultFallback = "payment_Globle_FallbackMethod")
public class PaymentService {

//正常访问返回ok的方法
@HystrixCommand
public String paymentInfo_OK(Integer id){
int age = 10/0;
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_OK, id:" + id + "\t" + "哈哈";
}

@HystrixCommand(fallbackMethod = "paymentInfo_TimeoutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})
public String paymentInfo_Timeout(Integer id){
long second = 3;
try {
TimeUnit.SECONDS.sleep(second);
}catch (InterruptedException e){
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "哈哈" + "耗时" +second+"秒钟";
}

public String paymentInfo_TimeoutHandler(Integer id){
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_Timeout, id:" + id + "\t" + "系统繁忙!请稍后再试!!";
}

//全局fallback方法
public String payment_Globle_FallbackMethod(){
return "系统繁忙!请稍后再试!!";
}
}



访问:http://localhost:8001/payment/hystrix/ok/31







相关推荐

评论 抢沙发

表情

分类选择