• Hystrix (容错,回退,降级,缓存)


    Hystrix熔断机制就像家里的保险丝一样,若同时使用高功率的电器,就会烧坏电路,这时候保险丝自动断开就有效的保护了电路。而我们程序中也同样是这样。例如若此时数据库压力太大速度很慢,此时还有不断的请求访问后台,就会造成数据库崩溃。这时候hystrix容错机制,可以为客户端请求设置超时链接,添加回退的逻辑,减少集群压力。

    1.1 导依赖

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.8.RELEASE</version> 
            <relativePath/>
        </parent>
        <!-- springCloud -->
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR3</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- eureka客户端依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <!-- hystrix -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-hystrix</artifactId>
            </dependency>

    1.2 配置application.yml

    # 指定端口
    server:
      port: 8085
      context-path: /demo
    # 服务名称
    spring:
      application:
        name: hystrix
    
    # eureka服务器地址
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/

    1.3 配置Hystrix过滤器

    import java.io.IOException;
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    import javax.servlet.annotation.WebFilter;
    import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;
    /**
     * urlPatterns:拦截所有路径(拦截规则)
     * filterName:过滤器名称
     */
    @WebFilter(urlPatterns = "/*", filterName = "hystrixFilter")
    public class HystrixFilterConf implements Filter{
        public void destroy() { }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            // 初始化Hystrix上下文
            HystrixRequestContext ctx = HystrixRequestContext.initializeContext();
            try {
                chain.doFilter(request, response);
            } catch (Exception e) {
                
            } finally {
                ctx.shutdown();
            }
        }
        public void init(FilterConfig arg0) throws ServletException { }
    }

    1.4 主函数入口

    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.boot.web.servlet.ServletComponentScan;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    @SpringBootApplication
    @EnableEurekaClient  //开启Eureka
    @EnableCircuitBreaker//开启断路器
    @ServletComponentScan//扫描servlet过滤器监听器
    public class ServerMain {
    
        public static void main(String[] args) {
            new SpringApplicationBuilder(ServerMain.class).web(true).run(args);
        }
    }

    二: hystrix 的 熔断,降级 机制。

    2.1 回退机制案例

    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
    import org.springframework.stereotype.Service;
    import org.springframework.web.bind.annotation.RequestMapping;
    /**
     * Hystrix回退机制(熔断,降级)
     */
    @Service
    public class RollbackService {
    
        /**
         * fallbackMethod: 指定回退方法
         * 
         * coreSize: 线程池最大数量
         * maxQueueSize: 线程池最大队列,默认-1通过SynchronousQueue来实现; 否则使用LinkedBlockingQueue实现
         * queueSizeRejectionThreshold: 当maxQueueSize是LinkedBlockingQueue时,即使没有达到最大列队也会据绝请求。
         * 
         * timeoutInMilliseconds: 超时时间
         * requestVolumeThreshold: 单位时间内超过这个多个请求失败才执行熔断
         */
        @RequestMapping(value = "/testRollback")
        @HystrixCommand(fallbackMethod = "myRollback", 
            threadPoolProperties = {
                @HystrixProperty(name = "coreSize", value = "30"), 
                @HystrixProperty(name = "maxQueueSize", value = "-1"),
                @HystrixProperty(name = "queueSizeRejectionThreshold", value = "-1")
            }, 
            commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000"),
                @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "1")
            })
        public String testRollback() {
            try {// 模拟请求阻塞
                Thread.sleep(4000);
            } catch (Exception e) {
            }
            return "恭喜你访问成功!";
        }
        /** 回退方法  */
        public String myRollback() {
            return "服务器压力过大,明年再来吧!";
        }
    }

    2.2 编写接口, 调用测试。

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class RollbackController {
    
        @Autowired
        private RollbackService rollbackService;
        
        @RequestMapping("/testRollback")
        public String testRollback() {
            return rollbackService.testRollback();
        }
    }

    三: hystrix 缓存机制:hystrix的缓存有点像mybatis默认开启的一级缓存:在session关闭之前(一次会话期间),使用同样的参数调用同一个方法,实际只查询一次。

    3.1 缓存逻辑

    import org.springframework.stereotype.Service;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
    import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
    @Service
    public class CacheService {
    
        @CacheResult
        @HystrixCommand
        public void cacheMember(Integer id) {
            System.out.println("调用 cacheMember 方法");
        }
        
        /**
         * commandKey:缓存的key
         *       获取和删除必须用同一个key,并必须是同一次请求。
         */
        @CacheResult
        @HystrixCommand(commandKey = "myCacheKey")
        public void getCache(Integer id) {
            System.out.println("执行查询方法");
        }
        @CacheRemove(commandKey = "myCacheKey")
        @HystrixCommand
        public void removeCache(Integer id) {
            System.out.println("删除缓存方法");
        }
    }

    3.2 缓存接口开发

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RestController;
    @RestController
    public class CacheController {
        
        @Autowired
        private CacheService cacheService;
    
        @RequestMapping(value = "/cache", method = RequestMethod.GET, 
                produces = MediaType.APPLICATION_JSON_VALUE)
        public String cache() {
            for(int i = 0; i < 3; i++) {
                /** 在同一次请求里面调用了3次同一方法,会发现,控制台只
                 *  输出了一次,说明后2次走的缓存没调方法的逻辑    */
                cacheService.cacheMember(1);
            }
            System.out.println("测试完毕");
            return "";
        }
        @RequestMapping(value = "/rc", method = RequestMethod.GET, 
                produces = MediaType.APPLICATION_JSON_VALUE)
        public String testRemoveCache() {
            cacheService.getCache(1);
            cacheService.getCache(1);
            
            cacheService.removeCache(1);
            System.out.println("#########  分隔线   ###########");
            cacheService.getCache(1);
            System.out.println("测试完毕");
            return "";
        }
    }

  • 相关阅读:
    深入理解计算机系统 第六章 存储器层次结构 第二遍
    深入理解计算机系统 第六章 存储器层次结构
    深入理解计算机系统 第八章 异常控制流 Part2 第二遍
    深入理解计算机系统 第八章 异常控制流 part2
    深入理解计算机系统 第八章 异常控制流 Part1 第二遍
    深入理解计算机系统 第八章 异常控制流 part1
    深入理解计算机系统 第三章 程序的机器级表示 Part2 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part2
    深入理解计算机系统 第三章 程序的机器级表示 Part1 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part1
  • 原文地址:https://www.cnblogs.com/wlwl/p/9476180.html
Copyright © 2020-2023  润新知