Spring Cloud自定义Hystrix请求命令

在上篇文章中,我们介绍了断路器Hystrix的一个简单使用,主要是通过注解来实现断路器的功能的,不过对于Hystrix的使用,除了注解,我们也可以使用继承类的方式来实现,本文我们就来看看另一种Hystrix的使用方式。



本文所使用的服务注册中心、服务提供者和服务消费者都是我们在前文中搭建出来的,这里我就不再赘述,不了解的小伙伴请翻看本系列前面几篇文章(文末提供了源码下载)。

自定义HystrixCommand

我们除了使用@HystrixCommand注解,也可以自定义类继承自HystrixCommand,如下:

public class BookCommand extends HystrixCommand<Book> {

    private RestTemplate restTemplate;

    @Override
    protected Book getFallback() {
        return new Book("宋诗选注", 88, "钱钟书", "三联书店");
    }

    public BookCommand(Setter setter, RestTemplate restTemplate) {
        super(setter);
        this.restTemplate = restTemplate;
    }

    @Override
    protected Book run() throws Exception {
        return restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class);
    }
}

在BookCommand中注入RestTemplate,然后重写两个方法:一个是getFallback,这个方法将在服务调用失败时回调;另一个是run方法,执行请求时调用。构造方法的第一个参数主要用来保存一些分组信息。

同步调用和异步调用

当BookCommand创建成功之后,我们就可以在我们的Controller中调用它了,如下:

@RequestMapping("/test1")
public Book test1() throws ExecutionException, InterruptedException {
    BookCommand bookCommand = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), restTemplate);
    //同步调用
    //Book book1 = bookCommand.execute();
    //异步调用
    Future<Book> queue = bookCommand.queue();
    Book book = queue.get();
    return book;
}

关于这一段调用,我说如下几点:

1.获取到BookCommand对象之后,我们有两种方式来执行请求,一种是调用execute方法发起一个同步请求,另一种是调用queue方法发起一个异步请求。 2.同步请求中可以直接返回请求结果。 3.异步请求中我们需要通过get方法来获取请求结果,在调用get方法的时候也可以传入超时时长。

执行结果如下:

如果我们先启动一个服务注册中心,再启动两个服务提供者实例,再启动一个服务消费者,然后再关掉一个服务提供者,此时再访问,就会间隔的看到如下页面:

通过注解实现异步请求

在上篇文章(Spring Cloud中的断路器Hystrix)中我们使用了注解来配置Hystrix,当时我们的写法如下:

@HystrixCommand
public Book test2() {
    return restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class);
}

那么这种请求是一种同步请求的方式,如果我们想要使用注解来实现异步请求怎么办呢?很简单,两个步骤:

1.配置HystrixCommandAspect的Bean

在项目的入口类中配置一个HystrixCommandAspect的Bean,如下:

@Bean
public HystrixCommandAspect hystrixCommandAspect() {
    return new HystrixCommandAspect();
}

2.通过AsyncResult来执行调用

还是使用@HystrixCommand注解,但是方法的实现使用AsyncResult,如下:

@HystrixCommand
    public Future<Book> test3() {
        return new AsyncResult<Book>() {
            @Override
            public Book invoke() {
                return restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class);
            }
        };
    }

OK,如此之后我们就可以通过注解来实现异步调用了。调用方式如下:

@RequestMapping("/test3")
public Book test3() throws ExecutionException, InterruptedException {
    Future<Book> bookFuture = bookService.test3();
    //调用get方法时也可以设置超时时长
    return bookFuture.get();
}

对响应式函数编程的支持

有的小伙伴可能对响应式函数编程情有独钟,Hystrix对此也提供了相应的支持,在我们获取到BookCommand对象之后,也可以通过如下两种方式来获取到一个Observable来对数据进行二次处理:

BookCommand bookCommand = new BookCommand(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("")), restTemplate);
        Observable<Book> observe = bookCommand.observe();
        Observable<Book> bookObservable = bookCommand.toObservable();

关于Observable小伙伴们可以自行度娘RxJava的用法,我这里就不再赘述,就说下observe和toObservable的区别:

1.observe命令在调用的时候会立即返回一个Observable。 2.toObservable则不会立即返回一个Observable,订阅者调用数据的时候才会执行。

通过注解支持响应式函数编程

当然,响应式函数编程也可以通过注解来实现,如下:

@HystrixCommand
public Observable<Book> test4() {
    return Observable.create(new Observable.OnSubscribe<Book>() {
        @Override
        public void call(Subscriber<? super Book> subscriber) {
            if (!subscriber.isUnsubscribed()) {
                Book book = restTemplate.getForObject("http://HELLO-SERVICE/getbook1", Book.class);
                subscriber.onNext(book);
                subscriber.onCompleted();
            }
        }
    });
}

这个时候我们可以通过在注解中添加参数来描述是通过observe还是toObservable来实现,如下:

@HystrixCommand(observableExecutionMode = ObservableExecutionMode.EAGER)表示使用observe模式来执行
@HystrixCommand(observableExecutionMode = ObservableExecutionMode.LAZY)表示使用toObservable模式来执行

OK,Hystrix自定义请求命令我们就先说这么多,整体上来看,还是注解要方便一些。下篇文章我们来看看服务降级的问题。

案例地址:https://github.com/lenve/SimpleSpringCloud

原文发布于微信公众号 - 玩转JavaEE(gh_d1ca11234a30)

原文发表时间:2017-09-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java学习123

查看Linux系统信息

296100
来自专栏java、Spring、技术分享

Hystrix源码解析

  在分布式系统中,难免有对外部接口的依赖,而外部接口有可能出现响应缓慢,大量请求超时,大量访问出现异常等情况。出现上面所说的情况有可能是由很多原因导制的,可能...

51430
来自专栏Kubernetes

Kubernetes Job Controller源码分析

Author: xidianwangtao@gmail.com 实现流程图 废话不多说,先把完整流程贴出来。 ? New JobController ty...

86680
来自专栏猿天地

知识点-Spring Boot 统一异常处理汇总

上面讲的是做页面开发的时候遇到的问题,还有一种情况就是用来开发Rest接口,当错误的时候我们希望返回给用户的是我们接口的标准格式,不是返回一段html代码。

16220
来自专栏小灰灰

Spring之RestTemplate中级使用篇

前面一篇介绍了如何使用RestTemplate发起post和get请求,然而也只能满足一些基本的场景,对于一些特殊的如需要设置请求头,添加认证信息等场景,却没有...

30310
来自专栏IT笔记

SpringBoot开发案例之整合Dubbo提供者(一)

既然是开发案例,显然不会扯那么多老婆舌,有不清楚这两个东东的请自行百度。 ? 0.jpg 开发环境 JDK1.7、Maven、Eclipse、SpringBoo...

451130
来自专栏A周立SpringCloud

如何使用Feign构造多参数的请求

最近经常有人在Spring Cloud中国社区(http://springcloud.cn)QQ群(157525002)里问到该问题。索性整理一下。 本节我们来...

57750
来自专栏JAVA技术站

JFinal整合Spring开发 原

思路大概是这样子的,首先需要初始化Spring的容器,把所有注解类加入到容器中,Spring里的AnnotationConfigApplicationConte...

10720
来自专栏Java技术栈

@Resource,@Autowired,@Inject3种注入方式详解

概况 @Resource,@Autowired,@Inject 这3种都是用来注入bean的,它们属于不同的程序中。 ANNOTATIONPACKAGESOUR...

40690
来自专栏猿天地

Spring Boot系列之环境搭建

16年开始就在写Spring Boot相关的文章了,之前一直是在自己猿天地的博客上发布,今年开始维护公众号,大部分时间都在写新的文章。

13530

扫码关注云+社区

领取腾讯云代金券