zoukankan      html  css  js  c++  java
  • springcloud(五) Hystrix 降级,超时

     分布式系统中一定会遇到的一个问题:服务雪崩效应或者叫级联效应
    什么是服务雪崩效应呢?
      在一个高度服务化的系统中,我们实现的一个业务逻辑通常会依赖多个服务,比如:
    商品详情展示服务会依赖商品服务, 价格服务, 商品评论服务. 调用三个依赖服务会共享商品详情服务的线程池. 如果其中的商品评论服务不可用, 就会出现线程池里所有线程都因等待响应而被阻塞, 从而造成服务雪崩. 如图所示:

    简单理解: 就是商品评论服务耗时假如是15S,那么在高并发的时候,其他服务很快就做出响应并把线程回收但是商品评论服务需要10S。在这10S内100个线程都会集中被消耗在商品评论服务,就造成商品评论服务没有线程对外提供服务了。
    服务雪崩效应:因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过
    程,就叫服务雪崩效应

    导致服务不可用的原因有几点: 程序Bug,大流量请求,硬件故障,缓存击穿
    【大流量请求】:在秒杀和大促开始前,如果准备不充分,瞬间大量请求会造成服务提供者的不可用.
    【硬件故障】:可能为硬件损坏造成的服务器主机宕机, 网络硬件故障造成的服务提供者的不可访问.
    【缓存击穿】:一般发生在缓存应用重启, 缓存失效时高并发, 所有缓存被清空时,以及短时间内大量缓存失效时. 大量的缓存不命中, 使请求直击后端,造成服务提供者超负荷运行,引起服务不可用。
    用户重试/代码逻辑重试,用户重试:在服务提供者不可用后, 用户由于忍受不了界面上长时间的等待,会不断刷新页面甚至提交表单,或者是代码有重试策略等等
    那么,归根结底导致雪崩效应的最根本原因是:大量请求线程同步等待造成的资源耗尽

    解决方案
    1. 超时机制
    2. 服务限流
    3. 服务熔断
    4. 服务降级 

    先启动Eureka 注册中心,代码就不上了,截图:


    order微服务工程

    pom.xml :

    <?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">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.tuling.cloud</groupId>
      <artifactId>microservice-consumer-order-ribbon-hystrix-fallback</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
      <name>06-ms-consumer-order-ribbon-hystrix-fallback</name>
    
      <!-- 引入spring boot的依赖 -->
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
      </parent>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
      </properties>
    
      <dependencies>
    
        <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>
    
        <!-- <artifactId>spring-cloud-starter-eureka</artifactId> 依赖了 <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> -->
        <!--  此包包含了eurekaclient,ribbon-->
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    
        <!-- hystrix 依赖-->
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
    
        <!-- feign 依赖-->
        <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    
      </dependencies>
    
      <!-- 引入spring cloud的依赖 -->
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Edgware.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
    
      <!-- 添加spring-boot的maven插件 -->
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
          </plugin>
        </plugins>
      </build>
    </project>
    

      OrderController.java:

    package com.jiagoushi.cloud.study.user.controller;
    
    import com.jiagoushi.cloud.study.user.entity.User;
    import com.jiagoushi.cloud.study.user.feign.UserFeignClient;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    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;
    import org.springframework.web.client.RestTemplate;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    
    /**
     * 演示 user服务挂了超时和执行请求超时
     */
    @RestController
    public class OrderController {
      private static final Logger logger = LoggerFactory.getLogger(OrderController.class);
    
      @Autowired
      private UserFeignClient userFeignClient;
    
      @Autowired
      private RestTemplate restTemplate;
    
      /**
       * Hystrix调用接口默认1秒超时,超时后会自动执行降级方法,可在文件配置,配置文件配置是全局的,
       * @HystrixCommand(fallbackMethod = "findByIdFallback") 注解也可以配置超时
       */
      @HystrixCommand(fallbackMethod = "findByIdFallback") // 基于注解的hystrix 推荐使用
      @GetMapping("/user/{id}")
      public User findById(@PathVariable Long id) {
    	logger.info("================请求用户中心接口==============");
        return this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
      }
    
      // 降级的方法
      public User findByIdFallback(Long id) { 
        User user = new User();
        user.setId(-1L);
        user.setName("降级用户");
        return user;
      }
    
    }
    

      ConsumerOrderApplication.java:

    package com.jiagoushi.cloud.study;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.cloud.netflix.feign.EnableFeignClients;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @EnableDiscoveryClient
    @SpringBootApplication
    @EnableCircuitBreaker//开启断路器功能
    public class ConsumerOrderApplication {
    
      @Bean
      @LoadBalanced
      public RestTemplate restTemplate() {
        return new RestTemplate();
      }
    
      public static void main(String[] args) {
        SpringApplication.run(ConsumerOrderApplication.class, args);
      }
    }
    

     


    user微服务:

    package com.tuling.cloud.study.controller;
    
    import java.util.Random;
    
    import org.apache.log4j.Logger;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.client.serviceregistry.Registration;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    import com.tuling.cloud.study.entity.User;
    import com.tuling.cloud.study.repository.UserRepository;
    
    @RestController
    public class UserController {
    	
      private final Logger logger = Logger.getLogger(getClass());
    	
      @Autowired
      private UserRepository userRepository;
      @Autowired
      private Registration registration;
      
    
      @GetMapping("/{id}")
      public User findById(@PathVariable Long id) throws Exception {
    	  logger.info("用户中心接口:查询用户"+ id +"信息");
    	  //模拟系统执行速度很慢的情况
    	  Thread.sleep(5000);
    	  
    	  User findOne = userRepository.findOne(id);
    	  return findOne;
      }
      
      @GetMapping("/getIpAndPort")
      public String findById() {
    	  return registration.getHost() + ":" + registration.getPort();
      }
    }
    

      user微服务在停止或者阻塞5s 的时候,order服务会走降级方法

     

    如何想修改接口超时间时间可以在order调用方修改yml 文件:

    server:
      port: 9010
    spring:
      application:
        name: microservice-consumer-order
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 3000 #命令执行超时时间,默认1000ms,就是调接口的响应时间超过3S就执行降级,不管提供者是否挂机还是延迟超过时间就走降级
  • 相关阅读:
    yii2 gii 命令行自动生成控制器和模型
    控制器中的方法命名规范
    Vue Property or method "" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based
    IDEA插件:GsonFormat
    Spring Boot : Access denied for user ''@'localhost' (using password: NO)
    Typora添加主题
    Git基础命令图解
    Java Joda-Time 处理时间工具类(JDK1.7以上)
    Java日期工具类(基于JDK1.7版本)
    Oracle SQL Developer 连接Oracle出现【 状态: 失败 -测试失败: ORA-01017: invalid username/password; logon denied】
  • 原文地址:https://www.cnblogs.com/smallFishs/p/10600517.html
Copyright © 2011-2022 走看看