java B2B2C Springcloud电子商务平台源码-Hystrix简单学习

Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离、信号量隔离、降级策略、熔断技术。在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有很多不可控的因素...

Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离、信号量隔离、降级策略、熔断技术。在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有很多不可控的因素,比如网络连接变慢,资源突然繁忙,暂时不可用,服务脱机等。我们要构建稳定、可靠的分布式系统,就必须要有这样一套容错方法。需要JAVA Spring Cloud大型企业分布式微服务云构建的B2B2C电子商务平台源码一零三八七七四六二六

举例子:

1.比如我们现在有3个业务调用分别是查询订单、查询商品、查询用户,且这三个业务请求都是依赖第三方服务-订单服务、商品服务、用户服务。三个服务均是通过RPC调用。当查询订单服务,假如线程阻塞了,这个时候后续有大量的查询订单请求过来,那么容器中的线程数量则会持续增加直致CPU资源耗尽到100%,整个服务对外不可用,集群环境下就是雪崩。

术语介绍:

1.1. Command

命令用于包裹对服务依赖或者外部系统的调用。

1.2. Circuit Breaker

类似于现实世界的断路器,起保护系统的作用。能够在一段时间内停止调用某个或者某些服务。

1.3. Fallback

Fallback的字面意思是回退、退路的意思。命令执行出错时,系统可以使用fallback,从而实现优雅降级。

1.4. Collapser

将若干命令合并成单一命令,可以减少调用次数。

pom.xml的依赖
 
<!-- 中央库:引入hystrix等-->
     <repository>
         <id>nexus</id>
         <name>local private nexus</name>
         <url>http://search.maven.org</url>
         <releases>
             <enabled>true</enabled>
         </releases>
         <snapshots>
             <enabled>false</enabled>
         </snapshots>
     </repository>  

          <!-- hystrix -->
          <hystrix.version>1.5.12</hystrix.version>     

     <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>${hystrix.version}</version>
      </dependency>
 
简单例子1:
 
package com.book.web.test.hystrix;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
/**
 * 入门
 * @author liweihan
 *
 */
public class CommandHelloWorld extends HystrixCommand<String> {
    
    private final String name;

    protected CommandHelloWorld(String name) {
        //最少配置:指定命令组名
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.name = name;
    }
    
    @Override
    protected String run() throws Exception {
        //a real example would do work like a network call here
        //依赖逻辑封装在run()方法中
        return "Hello " + name + "! thread: " + Thread.currentThread().getName();
    }
    
    
    public static void main(String[] args) throws Exception{
        /**
         * 每个Command对象只能调用一次,不可以重复调用
         * 重复调用对应的异常信息:This instance can only be executed once.
         * Please instantiate a new instance
         */
        CommandHelloWorld commandHelloWorld = new CommandHelloWorld("Synchronous-hystrix");
        //使用execute()同步调用代码,效果等同于:commandHelloWorld.queue().get();
        String s = commandHelloWorld.execute();
        System.out.println(" 同步 ====== " + s);
        
        //异步调用,可以自由控制获取结果的时机
        commandHelloWorld = new CommandHelloWorld("Asynchronous-hystrix");
        Future<String> future = commandHelloWorld.queue();
        //get()操作不能超过command定义的超时时间,默认为1秒
        s = future.get(100, TimeUnit.MILLISECONDS);
        System.out.println(" 异步 ====== " + s);
        
        
        System.out.println(" 主函数 ===== " + Thread.currentThread().getName());
        /**
         * 注意:
         * 异步调用使用 command.queue()get(timeout, TimeUnit.MILLISECONDS);
         * 同步调用使用command.execute() 等同于 command.queue().get();
         */
    }

}
 
简单例子2:
 
package com.book.web.test.hystrix;

import java.util.concurrent.TimeUnit;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;

/**
 * 测试4-熔断测试
 * @author liweihan
 *
 */
public class CommandHelloWorld5 extends HystrixCommand<String>{
    private Integer id;
    
    public CommandHelloWorld5(Integer id) {
        super(setter());
        this.id = id;
    }
    
    private static Setter setter() {
        return ApiSetter.setter("getNum");
                
    }

    @Override
    protected String run() throws Exception {
        if (id % 2 == 0 && id <= 10) { //让小于等于10的偶数返回
            return "running run():" + id;
        } else { //让奇数或大于10的数进入fallback
            TimeUnit.MILLISECONDS.sleep(200);
            return  " XXX ";
        }
    }
    
    @Override
    protected String getFallback() {
        return " ====== CircuitBreaker fallback" + id + " ,是否进入熔断:" + super.isCircuitBreakerOpen();
    }
    
    public static void main(String[] args) throws Exception {
        for(int i = 0; i < 30; i++) {
            System.out.println(new CommandHelloWorld5(i).execute());
            /*Future<String> future =  new CommandHelloWorld5(i).queue();
            System.out.println(future.get());*/
        }
    }
    
    private static class ApiSetter {

        public static Setter setter(String commandKeyName,String threadPoolKeyName) {
            return setter("ApiGroup",commandKeyName,threadPoolKeyName);
        }

        public static Setter setter(String commandKeyName) {
            return setter(commandKeyName,"Api-Pool");
        }

        /**
         * @author liweihan
         * @time 2017/12/20 16:57
         * @description     相关参数设置
         * @param groupKeyName      服务分组名
         * @param commandKeyName    服务标识名称
         * @param threadPoolKeyName 线程池名称
         * @return
         */
        public static Setter setter(String groupKeyName,String commandKeyName,String threadPoolKeyName) {
            //服务分组
            HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey(groupKeyName);
            //服务标识
            HystrixCommandKey commandKey = HystrixCommandKey.Factory.asKey(commandKeyName);
            //线程池名称
            HystrixThreadPoolKey threadPoolKey = HystrixThreadPoolKey.Factory.asKey(threadPoolKeyName);
            //线程配置
            HystrixThreadPoolProperties.Setter threadPoolProperties = HystrixThreadPoolProperties.Setter()
                    //设置核心线程池的大小,默认为10
                    .withCoreSize(25)
                    
                    //设置存活时间,单位分钟。如果coreSize小于maximumSize,那么该属性控制一个线程从实用完成到被释放的时间。默认为1
                    .withKeepAliveTimeMinutes(5)
                    
                    //设置BlockingQueue最大的队列值,默认值为-1
                    .withMaxQueueSize(Integer.MAX_VALUE)
                    
                    //设置队列拒绝的阈值——一个为设置的拒绝访问的最大队列值,即使maxQueueSize还没有达到。
                    //当将一个线程放入队列等待执行时,HystrixCommand使用该属性
                    //注意:如果maxQueueSize设置为-1,该属性不可用 ,默认为5
                    .withQueueSizeRejectionThreshold(10000);

            //命令属性的配置
            HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter()
                    .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                    //设置HystrixCommand.run()的执行是否有超时限制。默认是true
                    .withExecutionTimeoutEnabled(true)
                    
                    //使用线程隔离时,是否对命令执行超时的线程调用中断(Thread.interrupt())操作,默认是:true
                    //即:设置HystrixCommand.run()的执行是否在超时发生时被中断。
                    .withExecutionIsolationThreadInterruptOnTimeout(true) 
                    
                    //设置调用者等待命令执行的超时限制,超过此时间,HystrixCommand被标记为TIMEOUT,并执行回退逻辑。默认是1000ms
                    //注意:超时会作用在HystrixCommand.queue(),即使调用者没有调用get()去获得Future对象。
                    .withExecutionTimeoutInMilliseconds(100) 
                    
                    //使用线程隔离时,调用超时时间,默认:1秒  ,该方法已经不建议使用!
//                    .withExecutionIsolationThreadTimeoutInMilliseconds(3000)
                    
                    //失败率达到20%熔断器启动,默认值是50
                    .withCircuitBreakerErrorThresholdPercentage(20)
                    
                    // 置为true时,所有请求都将被拒绝,直接到fallback
                    //.withCircuitBreakerForceOpen(true)
                    
                    //10秒内请求超过5个的话才会启动熔断器,
                    //熔断器在设置在一个滚动窗口中,打开断路器的最少请求数。
                    //默认20。也就是10秒钟内至少请求20次,熔断器才发挥起作用 ,
                    //比如:如果值是20,在一个窗口内(比如10s),收到19个请求,即使这19个请求都失败了,熔断器也不会打开
                    //.withCircuitBreakerRequestVolumeThreshold(5)
                    
                    //是否启用熔断器,默认true. 启动 
                    .withCircuitBreakerEnabled(true) 
                    
                    //设置HystrixCommand.getCacheKey()是否启用,
                    //由HystrixRequestCache通过请求缓存提供去重复数据功能[默认为true]
                    .withRequestCacheEnabled(false)
                    ;

            //返回
            return HystrixCommand.Setter
                    .withGroupKey(groupKey)
                    .andCommandKey(commandKey)
                    .andThreadPoolKey(threadPoolKey)
                    .andThreadPoolPropertiesDefaults(threadPoolProperties)
                    .andCommandPropertiesDefaults(commandProperties);
        }
        
        /**
         * ☆参数说明:
             1.HystrixCommandGroupKey:服务分组,以上pydyn分组就包括多个服务,必填选项
             
             2.HystrixCommandKey:服务的名称,唯一标识,如果不配置,则默认是类名
             
             3.HystrixThreadPoolKey:线程池的名称,相同线程池名称的线程池是同一个,如果不配置,默认为分组名
             
             4.HystrixThreadPoolProperties:线程池的配置,
                 coreSize配置核心线程池的大小,
                 maxQueueSize线程池队列的最大大小,
                 queueSizeRejectionThreshold,限制当前队列的大小,
                 实际队列大小由这个参数决定,即到达队列里面条数到达10000,则都会被拒绝。
                 
             5.HystrixCommandProperties:配置命令的一些参数,
                 如executionIsolationStrategy,配置执行隔离策略,默认是使用线程隔离,THREAD即为线程池隔离,
                 
                 ExecutionIsolationThreadInterruptOnTimeout 使用线程隔离时,是否对命令执行超时的线程调用中断操作.默认:true
                 和ExecutionTimeoutInMilliseconds配置了启用超时和最大执行时间,这里为3s,
                 
                 circuitBreakerErrorThresholdPercentage失败率配置,默认为50%,
                 这里配置的为25%,即失败率到达25%触发熔断
         */
        
    }
}
 java B2B2C Springcloud电子商务平台源码


  • 发表于 2019-02-13 10:49
  • 阅读 ( 275 )
  • 分类:Java基础

条评论

请先 登录 后评论
不写代码的码农
IT 小兵

355 篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除