构建cloud-provider-hystrix-payment8001

pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2020</artifactId>
  7. <groupId>com.carve.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-provider-hystrix-payment8001</artifactId>
  12. <dependencies>
  13. <!--hystrix-->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  17. </dependency>
  18. <!--eureka client-->
  19. <dependency>
  20. <groupId>org.springframework.cloud</groupId>
  21. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>com.carve.springcloud</groupId>
  25. <artifactId>cloud-api-common</artifactId>
  26. <version>${project.version}</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-web</artifactId>
  31. </dependency>
  32. <!--监控-->
  33. <dependency>
  34. <groupId>org.springframework.boot</groupId>
  35. <artifactId>spring-boot-starter-actuator</artifactId>
  36. </dependency>
  37. <!--热部署-->
  38. <dependency>
  39. <groupId>org.springframework.boot</groupId>
  40. <artifactId>spring-boot-devtools</artifactId>
  41. <scope>runtime</scope>
  42. <optional>true</optional>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.projectlombok</groupId>
  46. <artifactId>lombok</artifactId>
  47. <optional>true</optional>
  48. </dependency>
  49. <dependency>
  50. <groupId>org.springframework.boot</groupId>
  51. <artifactId>spring-boot-starter-test</artifactId>
  52. <scope>test</scope>
  53. </dependency>
  54. </dependencies>
  55. </project>

yml

  1. server:
  2. port: 8001
  3. spring:
  4. application:
  5. name: cloud-provider-hystrix-payment
  6. eureka:
  7. client:
  8. register-with-eureka: true
  9. fetch-registry: true
  10. service-url:
  11. defaultZone: http://eureka7001.com:7001/eureka
  12. # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka # 集群版

启动类

  1. @SpringBootApplication
  2. @EnableEurekaClient
  3. public class PaymentHystrixMain8001 {
  4. public static void main(String[] args) {
  5. SpringApplication.run(PaymentHystrixMain8001.class, args);
  6. }
  7. }

service

  1. @Service
  2. public class PaymentService {
  3. // 正常访问
  4. public String paymentInfo_OK(Integer id) {
  5. return "线程池:" + Thread.currentThread().getName() + " paymentInfo_OK(),id:" + id;
  6. }
  7. // 超时访问
  8. public String paymentInfo_TimeOut(Integer id) {
  9. int timeNumber = 3;
  10. try {
  11. TimeUnit.SECONDS.sleep(timeNumber);
  12. } catch (InterruptedException e) {
  13. e.printStackTrace();
  14. }
  15. return "线程池:" + Thread.currentThread().getName() + " paymentInfo_TimeOut(),id:" + id + " 耗时(秒)" + timeNumber;
  16. }
  17. }

controller

  1. @RestController
  2. @Slf4j
  3. public class PaymentController {
  4. @Resource
  5. private PaymentService paymentService;
  6. // 正常访问
  7. @GetMapping("/payment/hystrix/ok/{id}")
  8. public String paymentInfo_OK(@PathVariable("id") Integer id) {
  9. String result = paymentService.paymentInfo_OK(id);
  10. log.info("*****result:" + result);
  11. return result;
  12. }
  13. // 超时访问
  14. @GetMapping("/payment/hystrix/timeout/{id}")
  15. public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
  16. String result = paymentService.paymentInfo_TimeOut(id);
  17. log.info("*****result:" + result);
  18. return result;
  19. }
  20. }

正常测试

启动eureka7001
启动eureka-provider-hystrix-payment8001
访问 http://localhost:8001/payment/hystrix/ok/31
访问 http://localhost:8001/payment/hystrix/timeout/31 每次调用耗时3秒

接下来,以上述为根基平台,从正确->错误->降级熔断->恢复

高并发测试

Jmeter压测测试

https://jmeter.apache.org/download_jmeter.cgi

开启Jmeter,来2w个并发压死8001, 2w个请求都去访问paymentInfo_TimeOut服务
然后访问 http://localhost:8001/payment/hystrix/timeout/31
搜狗截图20200824210718.png
搜狗截图20200824211224.png

Jmeter压测结论

卡死原因: tomcat的默认工作线程数被打满了,没有多余的线程分解压力和处理
搜狗截图20200824211245.png
上面还只是服务提供者8001自己测试,假如此时外部的消费者80也来访问,那消费者只能干等,最终导致消费端80不满意,服务端8001直接被拖死

加入cloud-consumer-feign-hystrix-order80

pom

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <parent>
  6. <artifactId>cloud2020</artifactId>
  7. <groupId>com.carve.springcloud</groupId>
  8. <version>1.0-SNAPSHOT</version>
  9. </parent>
  10. <modelVersion>4.0.0</modelVersion>
  11. <artifactId>cloud-consumer-feign-hystrix-order80</artifactId>
  12. <dependencies>
  13. <!--openfeign-->
  14. <dependency>
  15. <groupId>org.springframework.cloud</groupId>
  16. <artifactId>spring-cloud-starter-openfeign</artifactId>
  17. </dependency>
  18. <!--eureka client-->
  19. <dependency>
  20. <groupId>org.springframework.cloud</groupId>
  21. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>com.carve.springcloud</groupId>
  25. <artifactId>cloud-api-common</artifactId>
  26. <version>${project.version}</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-web</artifactId>
  31. </dependency>
  32. <!--监控-->
  33. <dependency>
  34. <groupId>org.springframework.boot</groupId>
  35. <artifactId>spring-boot-starter-actuator</artifactId>
  36. </dependency>
  37. <!--热部署-->
  38. <dependency>
  39. <groupId>org.springframework.boot</groupId>
  40. <artifactId>spring-boot-devtools</artifactId>
  41. <scope>runtime</scope>
  42. <optional>true</optional>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.projectlombok</groupId>
  46. <artifactId>lombok</artifactId>
  47. <optional>true</optional>
  48. </dependency>
  49. <dependency>
  50. <groupId>org.springframework.boot</groupId>
  51. <artifactId>spring-boot-starter-test</artifactId>
  52. <scope>test</scope>
  53. </dependency>
  54. </dependencies>
  55. </project>

yml

  1. server:
  2. port: 80
  3. eureka:
  4. client:
  5. register-with-eureka: false
  6. fetch-registry: true
  7. service-url:
  8. defaultZone: http://eureka7001.com:7001/eureka
  9. # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

启动类

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

service

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

    // 正常访问
    @GetMapping("/payment/hystrix/ok/{id}")
    String paymentInfo_OK(@PathVariable("id") Integer id);

    // 超时访问
    @GetMapping("/payment/hystrix/timeout/{id}")
    String paymentInfo_TimeOut(@PathVariable("id") Integer id);

}

controller

@RestController
@Slf4j
public class OrderHyrixController {
    @Autowired
    private PaymentHystrixService paymentHystrixService;

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

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

测试

正常访问 http://localhost/consumer/payment/hystrix/ok/32

开启Jmeter,来2w个并发压死8001
http://localhost/consumer/payment/hystrix/ok/32
消费者80, 要么转圈圈, 要么消费端报超时错误
1542615-20200823152857145-1578071214.png

如何解决?解决的要求

超时导致服务器变慢(转圈) -> 超时不再等待
出错(宕机或程序运行出错) -> 出错要有兜底

解决

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