美文网首页java高级开发
SpringCloud-hystrix 理解服务容错保护

SpringCloud-hystrix 理解服务容错保护

作者: 老鼠AI大米_Java全栈 | 来源:发表于2018-09-24 22:34 被阅读21次

    微服务架构中,系统往往拆分成多个服务单元,各单元的应用间通过服务注册与订阅方式相互依赖,由于各单元都在不同的进程中运行,依赖通过远程调用的方式执行,可能会因为网络原因导致调用失败,就需要服务容错保护。

    下面创建一个hystrix客户端,点击这里创建一个Gradle工程,boot版本用1.5.x,添加依赖如下:

    dependencyManagement {
        imports {
            mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Edgware.SR4'
        }
    }
    
    dependencies {
        compile('org.springframework.boot:spring-boot-starter')
        compile('org.springframework.boot:spring-boot-starter-web')
        compile('org.springframework.boot:spring-boot-starter-actuator')
        compile 'org.slf4j:slf4j-api:1.7.14'
        compile('org.springframework.cloud:spring-cloud-starter-hystrix')
        compile('org.springframework.cloud:spring-cloud-starter-eureka')
        compile('org.springframework.cloud:spring-cloud-starter-ribbon')
        testCompile('org.springframework.boot:spring-boot-starter-test')
    }
    

    然后编写配置文件application.properties

    spring.application.name=hystrix-base
    server.port=8088
    
    eureka.client.serviceUrl.defaultZone=http://peer1:1111/eureka/,http://peer1:1111/eureka/
    

    注意,先启动上一章中的注册中心服务,单机或集群都可以。

    打开断路器,2种方式

    @EnableHystrix
    or
    @EnableCircuitBreaker
    

    @EnableHystrix包含@EnableCircuitBreaker

    编写controller,模拟服务超时引发断路,如下:

    @RestController
    public class HystrixDemoController {
        private final static Random random = new Random();
    
        @GetMapping("hello")
        @HystrixCommand(fallbackMethod = "error",commandProperties = {
                @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "100")
        })
        public String hello()throws Exception{
            int value = random.nextInt(200);
            System.out.println("hello() costs "+ value + " ms.");
            Thread.sleep(value);
            return "hello";
        }
    
        public String error(){
            return "error";
        }
    

    上面的代码,定义一个hello接口,使用@HystrixCommand配置接口断路超时时间为100毫秒,即超过100毫秒即引发断路。
    启动服务,可以在注册中心http://localhost:1111/看到注册的服务,然后输入http://localhost:8088/hello并不断刷新,可以看到超时时会输出error。

    其实,我们可以使用future模拟实现hystrix下,简单理解hystrix,如:

    Random random = new Random();
            ExecutorService service = Executors.newFixedThreadPool(1);
            Future<String> future = service.submit(()->{
                int value = random.nextInt(200);
                System.out.println("hello() costs "+ value + " ms.");
                Thread.sleep(value);
                return "hello";
            });
            try {
                future.get(100, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                System.out.println("超时保护!");
            }
    

    先创建一个线程池,然后提交一个任务得到future,给get设置时间限制,超出则报异常。

    若使用future模拟hystrix是优秀的,那另一种方式将是卓越的,就是rxjava,下面先了解下线程控制的几个方法:

    //直接在当前线程运行
    Schedulers.immediate()
    //启动新线程并在新线程执行操作
    Schedulers.newThread()
    //内部实现一个无上限的线程池,可重用空闲线程
    Schedulers.io()
    

    接下来,我们用rxjava实现一下hystrix,如下:

    Random random = new Random();
            Single.just("Hello")
                    .subscribeOn(Schedulers.immediate()) 
                    .subscribe(new Observer<String>() {
                        @Override
                        public void onCompleted() {
                            System.out.println("执行完毕!");
                        }
                        @Override
                        public void onError(Throwable e) {
                            System.out.println("熔断保护!");
                        }
                        @Override
                        public void onNext(String s) {
                            int value = random.nextInt(200);
                            System.out.println("hello() costs "+ value + " ms.");
                            if (value > 100) {
                                throw new RuntimeException("Timeout!");
                            }
                        }
                    });
    

    上面就是在当前线程中发射字符串hello,若大于100毫秒则抛异常进入onError,否则进入onCompleted。
    通过上面2种方式的模拟,相信大家对hystrix不再陌生,但是对它的使用还不太熟悉吧,除了注解的方式,我们还将介绍另一种方式--编程方式,如下:

        @GetMapping("hello2")
        public String hello2()throws Exception{
            return new HelloCommand().execute();
        }
    
        private class HelloCommand extends com.netflix.hystrix.HystrixCommand<String> {
            protected HelloCommand(){
                super(HystrixCommandGroupKey.Factory.asKey("Hello"),100);//100毫秒
            }
    
            @Override
            protected String run() throws Exception {
                int value = random.nextInt(200);
                System.out.println("hello2() costs "+ value + " ms.");
                Thread.sleep(value);
                return "hello2";
            }
    
            @Override
            protected String getFallback() {
                return HystrixDemoController.this.error();
            }
        }
    

    这是通过继承HystrixCommand实现自定义命令,可以更新灵活的实现自己的需求,但写法比较复杂。
    学习交流,请加群:64691032

    相关文章

      网友评论

        本文标题:SpringCloud-hystrix 理解服务容错保护

        本文链接:https://www.haomeiwen.com/subject/btxhoftx.html