资讯专栏INFORMATION COLUMN

Hystrix命令入门使用

Maxiye / 2429人阅读

摘要:主要介绍各接口和注解的使用方法。创建请求命令命令就是我们之前所说的,他用来封装具体的依赖服务调用逻辑。通过调用和可以返回对象,如下前者返回的是一个,该命令会在调用的时候立即执行,当每次被订阅的时候都会重放它的行为。表示使用执行方式。

主要介绍Hystrix各接口和注解的使用方法。

创建请求命令

Hystrix命令就是我们之前所说的HystrixCommand,他用来封装具体的依赖服务调用逻辑。

继承方式实现HystrixCommand

首先通过代码实现HystrixCommand

package cn.sh.ribbon.command;

import cn.sh.common.entity.User;
import com.netflix.hystrix.HystrixCommand;
import org.springframework.web.client.RestTemplate;

/**
 * @author sh
 */
public class UserCommand extends HystrixCommand {

    private RestTemplate restTemplate;

    private Long id;

    public UserCommand(Setter setter, RestTemplate restTemplate, Long id) {
        super(setter);
        this.restTemplate = restTemplate;
        this.id = id;
    }
    
    @Override
    protected User run() throws Exception {
        return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
    }

}

通过上面实现的UserCommand,我们即可以实现请求的同步执行也可以实现异步执行,相关代码如下:

package cn.sh.ribbon.service;

import cn.sh.common.entity.User;
import cn.sh.ribbon.command.UserCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @author sh
 */
@Service
public class HelloService {

    private static final Logger logger = LoggerFactory.getLogger(HelloService.class);

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 第一种使用命令的方式
     * @param id
     * @return
     */
    public User getUserById(Long id) {
        HystrixCommandGroupKey groupKey = HystrixCommandGroupKey.Factory.asKey("userKey");
        com.netflix.hystrix.HystrixCommand.Setter setter = com.netflix.hystrix.HystrixCommand.Setter.withGroupKey(groupKey);
        UserCommand userCommand = new UserCommand(setter, restTemplate, id);
        // 同步执行获取结果
//        return userCommand.execute();
        // 异步执行获取结果
        Future future = userCommand.queue();
        try {
            return future.get();
        } catch (Exception e) {
            logger.info("获取结果发生异常", e);
        }
        return null;
    }

}
注解方式使用HystrixCommand

通过HystrixCommand注解可以更优雅的实现Hystrix命令的定义,如下:

package cn.sh.ribbon.service;

import cn.sh.common.entity.User;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
 * @author sh
 */
@Service
public class HelloService {

    private static final Logger logger = LoggerFactory.getLogger(HelloService.class);

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 通过注解方式获取User
     * @param id
     * @return
     */
    @HystrixCommand
    public User findUserById(Long id) {
        return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
    }
}

上述代码虽然可以优雅的实现Hystrix命令,但是上述获取User的方式只是同步执行的实现,如果需要实现异步执行则需要进行如下改造:

package cn.sh.ribbon.service;

import cn.sh.common.entity.User;
import cn.sh.ribbon.command.UserCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.command.AsyncResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import rx.Subscription;
import rx.functions.Action1;

import java.util.concurrent.Future;

/**
 * @author sh
 */
@Service
public class HelloService {

    private static final Logger logger = LoggerFactory.getLogger(HelloService.class);

    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 通过注解方式异步执行获取User
     * @param id
     * @return
     */
    @HystrixCommand
    public Future asyncFindUserFutureById(Long id) {
        return new AsyncResult() {
            @Override
            public User invoke() {
                return restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
            }
        };
    }
}
响应执行

除了传统的同步执行与异步执行之外,我们还可以将HystrixCommand通过Observable来实现响应式执行方式。通过调用observe()和toObservable()可以返回Observable对象, 如下:

Observable observe = userCommand.observe();
Observable observe = userCommand.toObservable();

前者返回的是一个Hot Observable,该命令会在observe调用的时候立即执行,当Observable每次被订阅的时候都会重放它的行为。

后者返回的是一个Cold Observable,toObservable()执行之后,命令不会被立即执行,只有当所有订阅者都订阅他之后才会执行。

HystrixCommand具备了observe()和toObservable()的功能,但是它的实现有一定的局限性,它返回的Observable只能发射一次数据,所以Hystrix提供了另外的一个特殊命令封装HysrtixObservableCommand,通过命令可以发射多次的Observable

响应执行自定义命令

相关代码如下:

package cn.sh.ribbon.command;

import cn.sh.common.entity.User;
import com.netflix.hystrix.HystrixObservableCommand;
import org.springframework.web.client.RestTemplate;
import rx.Observable;

/**
 * @author sh
 */
public class UserObservableCommand extends HystrixObservableCommand {

    private RestTemplate restTemplate;

    private Long id;

    public UserObservableCommand (Setter setter, RestTemplate restTemplate, Long id) {
        super(setter);
        this.restTemplate = restTemplate;
        this.id = id;
    }

    @Override
    protected Observable construct() {
        return Observable.create(subscriber -> {
            if (!subscriber.isUnsubscribed()) {
                User user = restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
                subscriber.onNext(user);
                subscriber.onCompleted();
            }
        });
    }
}
响应执行使用注解@HystrixCommand

相关代码如下:

package cn.sh.ribbon.service;

import cn.sh.common.entity.User;
import cn.sh.ribbon.command.UserCommand;
import cn.sh.ribbon.command.UserObservableCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.command.AsyncResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.Subscription;

/**
 * @author sh
 */
@Service
public class HelloService {

    private static final Logger logger = LoggerFactory.getLogger(HelloService.class);

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 使用注解实现响应式命令
     * @param id
     * @return
     */
    @HystrixCommand
    public Observable observableGetUserId(Long id) {
        return Observable.create(subscriber -> {
            if (!subscriber.isUnsubscribed()) {
                User user = restTemplate.getForObject("http://USER-SERVICE/users/{1}", User.class, id);
                subscriber.onNext(user);
                subscriber.onCompleted();
            }
        });
    }

}

使用@HystrixCommand注解实现响应式命令,可以通过observableExecutionMode参数来控制是使用observe()还是toObservable()的执行方式。该参数有下面两种设置方式:

@HystrixCommand(observableExecutionMode = ObservableExecutionMode.EAGER): EAGER是该参数的模式值,表示使用observe()执行方式。

@HystrixCommand(observableExecutionMode = ObservableExecutionMode.LAZY): 表示使用toObservable()执行方式。

代码地址

spring-cloud-example

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76981.html

相关文章

  • Spring Cloud Hystrix入门Hystrix命令原理分析

    摘要:系统需要支持命令的撤销。第步计算断路器的健康度会将成功失败拒绝超时等信息报告给断路器,断路器会维护一组计数器来统计这些数据。第步,当前命令的线程池请求队列或者信号量被占满的时候。 断路由器模式 在分布式架构中,当某个服务单元发生故障之后,通过断路由器的故障监控(类似熔断保险丝),向调用方返回一个错误响应,而不是长时间的等待。这样就不会使得线程因调用故障服务被长时间占用不释放,避免了故障...

    Betta 评论0 收藏0
  • Hystrix基础入门和特性讲解

    摘要:断路器本身是一种开关装置,用于在电路上保护线路过载,当线路中有电器发生短路时,断路器能够及时的切断故障电路,防止发生过载发热甚至起火等严重后果。具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能。 转载请注明出处 http://www.paraller.com 代码机制:熔断 & Fallback & 资源隔离 熔断 概念: 在微服务架构中,我们将系...

    dkzwm 评论0 收藏0
  • 两年了,我写了这些干货!

    摘要:开公众号差不多两年了,有不少原创教程,当原创越来越多时,大家搜索起来就很不方便,因此做了一个索引帮助大家快速找到需要的文章系列处理登录请求前后端分离一使用完美处理权限问题前后端分离二使用完美处理权限问题前后端分离三中密码加盐与中异常统一处理 开公众号差不多两年了,有不少原创教程,当原创越来越多时,大家搜索起来就很不方便,因此做了一个索引帮助大家快速找到需要的文章! Spring Boo...

    宋华 评论0 收藏0
  • 两年了,我写了这些干货!

    摘要:开公众号差不多两年了,有不少原创教程,当原创越来越多时,大家搜索起来就很不方便,因此做了一个索引帮助大家快速找到需要的文章系列处理登录请求前后端分离一使用完美处理权限问题前后端分离二使用完美处理权限问题前后端分离三中密码加盐与中异常统一处理 开公众号差不多两年了,有不少原创教程,当原创越来越多时,大家搜索起来就很不方便,因此做了一个索引帮助大家快速找到需要的文章! Spring Boo...

    huayeluoliuhen 评论0 收藏0
  • Hystrix使用

    1. Hystrix是谁? Hystrix源于Netflix API团队在2011年启动的弹性工程工作,而目前它在Netflix每天处理着数百亿的隔离线程以及数千亿的隔离信号调用。该库旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能。目前托管在github上...

    harryhappy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<