欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpingCloud(H版&alibaba)框架开发教程-27 Hystrix微服务搭建及服务降级

程序员文章站 2022-06-21 13:43:52
2020最新版SpringCloud(H版&alibaba)框架开发教程-周阳cloud-eureka-server7001模块将Eureka服务改为单机版,修改yml配置文件defaultZone: http://eureka7001.com:7001/eureka/cloud-provider-hystrix-payment8001模块微服务模块1. 建moduleNew --> Module --> Maven[Module SDK:1.8.0_191] --....

2020最新版SpringCloud(H版&alibaba)框架开发教程-周阳

cloud-eureka-server7001模块

将Eureka服务改为单机版,修改yml配置文件

defaultZone: http://eureka7001.com:7001/eureka/

cloud-provider-hystrix-payment8001模块

1. 建module

New --> Module --> Maven[Module SDK:1.8.0_191] --> name[cloud-provider-hystrix-payment8001] --> Finish

2. 改pom

<?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.antherd.springcloud</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>cloud-provider-hystrix-payment8001</artifactId>

  <dependencies>
    <!-- hystrix -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-hystrix</artifactId>
      <version>1.4.7.RELEASE</version>
    </dependency>
    <!--eureka client-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--引入公共api包-->
    <dependency>
      <groupId>com.antherd.springcloud</groupId>
      <artifactId>cloud-api-commons</artifactId>
      <version>${project.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-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>
  </dependencies>
</project>

3. 写yml

server:
  port: 8001

spring:
  application:
    name: cloud-provider-hystrix-payment

eureka:
  client:
    register-with-eureka: true
    fetchRegistry: true
    service-url:
      defaultZone: http://localhost:7001/eureka

4. 主启动
新建类:com.antherd.springcloud.PaymentHystrixMain8001

package com.antherd.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class PaymentHystrixMain8001 {

  public static void main(String[] args) {

    SpringApplication.run(PaymentHystrixMain8001.class, args);
  }
}

新建类:com.antherd.srpingcloud.service.PaymentService

package com.antherd.springcloud.service;

import java.util.concurrent.TimeUnit;
import org.springframework.stereotype.Service;

@Service
public class PaymentService {

  public String paymentInfoOk(Integer id) {
    return "线程池:" + Thread.currentThread().getName() + " paymentInfoOk," + id + " O(∩_∩)O哈哈~";
  }

  public String paymentInfoTimeout(Integer id) {
    int timeNumber = 3;
    try {
      TimeUnit.SECONDS.sleep(timeNumber);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    return "线程池:" + Thread.currentThread().getName() + " paymentInfoTimeout," + id + " ┭┮﹏┭┮" + " 耗时" + timeNumber + "秒钟";
  }
}

新建类:com.antherd.srpingcloud.contorller.PaymentController

package com.antherd.springcloud.controller;

import com.antherd.springcloud.service.PaymentService;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
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 {

  @Resource
  private PaymentService paymentService;

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

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

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

5. 启动测试

启动:cloud-eureka-server7001,cloud-provider-hystrix-payment8001两个模块

访问:http://localhost:8001/payment/hystrix/ok/1http://localhost:8001/payment/hystrix/timeout/1 发现都可以正常访问

如果此时用jmeter对http://localhost:8001/payment/hystrix/timeout/1 进行100线程20次压测,会发现http://localhost:8001/payment/hystrix/ok/1的响应也会变慢。

ps:Tomecat默认线程量为10。

cloud-consumer-feign-hystrix-order80模块

1. 建module

New --> Module --> Maven[Module SDK:1.8.0_191] --> name[cloud-consumer-feign-hystrix-order80] --> Finish

2. 改pom

<?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.antherd.springcloud</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>cloud-consumer-feign-hystrix-order80</artifactId>

  <dependencies>
    <!-- openfeign -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
      <version>2.2.1.RELEASE</version>
    </dependency>
    <!--eureka client-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!--引入公共api包-->
    <dependency>
      <groupId>com.antherd.springcloud</groupId>
      <artifactId>cloud-api-commons</artifactId>
      <version>${project.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-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>
  </dependencies>
</project>

3. 写yml

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

4. 主启动
新建类:com.antherd.springcloud.OrderHystrixMain80

package com.antherd.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);
  }
}

新建类:com.antherd.srpingcloud.service.PaymentHystrixService

package com.antherd.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("CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixService {

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

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

}

新建类:com.antherd.srpingcloud.contorller.OrderHystrixController

package com.antherd.springcloud.controller;

import com.antherd.springcloud.service.PaymentHystrixService;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
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 OrderHystrixController {

  @Resource
  private PaymentHystrixService paymentHystrixService;

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

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

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

5. 启动测试

启动:cloud-eureka-server7001,cloud-provider-hystrix-payment8001,cloud-consumer-feign-hystrix-order80三个模块

访问:http://localhost/consumer/payment/hystrix/ok/1 发现可以正常访问、http://localhost/consumer/payment/hystrix/timeout/1 发现访问超时直接显示了报错页面

解决

对方服务(8001)超时了,调用者(80)不能一直卡死等待,必须有服务降级
对方服务(8001)down机了,调用者(80)不能一直卡死等待,必须有服务降级
对方服务(8001)OK,调用者(80)自己出故障或有自我要求(自己的等待时间小于服务提供者),自己处理降级

cloud-provider-hystrix-payment8001模块

设置自身调用超时时间的峰值(3s),峰值内可以正常运行,超过了需要兜底的方法处理,作服务降级fallback

修改com.antherd.springcloud.service.PaymentService.paymentInfoTimeout方法,处理时间改为5秒,同时添加fallback注解

@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandle", commandProperties = {
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
  })
public String paymentInfoTimeout(Integer id) {
  int timeNumber = 5;
  try {
    TimeUnit.SECONDS.sleep(timeNumber);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  return "线程池:" + Thread.currentThread().getName() + " id:" + id + " O(∩_∩)O哈哈~" + " 耗时" + timeNumber + "秒钟";
}

并且编写对应的fallback方法paymentInfoTimeoutHandle

public String paymentInfoTimeoutHandle(Integer id) {
    return "线程池:" + Thread.currentThread().getName() + " id:" + id + " 8001系统繁忙或运行报错,请稍后再试" + " ┭┮﹏┭┮";
}

在主启动类上添加注解激活服务降级

@EnableEurekaClient
@EnableCircuitBreaker

启动:cloud-eureka-server7001,cloud-provider-hystrix-payment8001两个模块

访问:http://localhost:8001/payment/hystrix/timeout/1 发现访问没有报错,等待3秒后执行paymentInfoTimeoutHandle方法并且返回结果

现在,我们在paymentInfoTimeout方法开始位置添加异常代码

int age = 10/0;

访问:http://localhost:8001/payment/hystrix/timeout/1 发现立刻执行paymentInfoTimeoutHandle方法并且返回结果,不会等待3秒超时

cloud-consumer-feign-hystrix-order80模块

pom文件中添加Hystrix依赖

<!-- hystrix -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-hystrix</artifactId>
  <version>1.4.7.RELEASE</version>
</dependency>

修改application.yml配置,添加

ribbon:
  ConnectTimeout: 5000
  ReadTimeout: 5000

添加@EnableHystrix注解及对@HystrixCommand内属性的修改建议重启微服务,否则可能不生效

在启动类com.antherd.springcloud.OrderHystrixMain80上加上注解

@EnableHystrix

修改类:com.antherd.springcloud.controller.OrderHystrixController

@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandle", commandProperties = {
    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
})
public String paymentInfoTimeout(@PathVariable("id") Integer id) {
  return paymentHystrixService.paymentInfoTimeout(id);
}

public String paymentInfoTimeoutHandle(@PathVariable("id") Integer id) {
  return "我是消费者80,对方支付系统繁忙请10秒后再试或者自己运行出错请检查自己,┭┮﹏┭┮";
}

同时把8001模块com.antherd.springcloud.service.PaymentService.paymentInfoTimeout方法改为如下

@HystrixCommand(fallbackMethod = "paymentInfoTimeoutHandle", commandProperties = {
      @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
})
public String paymentInfoTimeout(Integer id) {
  // int age = 10/0;
  int timeNumber = 3;
  try {
    TimeUnit.SECONDS.sleep(timeNumber);
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
  return "线程池:" + Thread.currentThread().getName() + " id:" + id + " O(∩_∩)O哈哈~" + " 耗时" + timeNumber + "秒钟";
}

访问:http://localhost/consumer/payment/hystrix/timeout/1,发现消费侧启动了服务降级。然后把com.antherd.springcloud.controller.OrderHystrixController.paymentInfoTimeout 的服务降级时间改为4秒,发现可以正常访问接口。

本文地址:https://blog.csdn.net/REX1129/article/details/111992886