当前位置: > > > SpringCloud - 服务容错保护组件Hystrix的使用详解2(创建请求命令)

SpringCloud - 服务容错保护组件Hystrix的使用详解2(创建请求命令)

二、创建请求命令

1,Hystrix 命令介绍

(1)Hystrix 命令就是我们前面说的 HystirxCommand,它用来封装具体的依赖服务调用逻辑。
  • 通过其 execute() 方法和 queue() 方法可以分别实现请求的同步执行、异步执行。
  • 除此之外还可以调用其 observe() 方法和 toObservable()方法返回 Observable 对象,从而实现响应式执行方式。
(2)我们除了可以通过继承 HystirxCommand 的方式实现 Hystrix 命令外,也可以通过 @HystrixCommand 注解更为优雅地实现 Hystrix 命令的定义,下面通过样例进行演示。

2,同步执行方式

(1)实现同步执行的命令很简单,只要在方法上添加 @HystrixCommand 注解即可:
@Service
public class HelloService {

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand
    public String hello() {
        String result = restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class)
                .getBody();
        return result;
    }
}

(2)同步命令的调用执行也很简单:
@RestController
public class ConsumerController {
    @Autowired
    HelloService helloService;

    @GetMapping("/hello-consumer")
    public String helloConsumer() {
        return helloService.hello();
    }
}

3,异步执行方式

(1)下面定义一个异步执行方式的命令,其返回的是一个 Future 对象: 
@Service
public class HelloService {

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand
    public Future<String> hello() {
        return new AsyncResult<String>() {
            @Override
            public String invoke() {
                return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class)
                        .getBody();
            }
        };
    }
}

(2)异步命令的调用执行方式如下:
@RestController
public class ConsumerController {
    @Autowired
    HelloService helloService;

    @GetMapping("/hello-consumer")
    public String helloConsumer() throws InterruptedException, ExecutionException {
        return helloService.hello().get();
    }
}

4,响应式执行方式 

(1)在使用 @HystrixCommand 注解实现响应式命令时,可以通过 observableExecutionMode 参数来控制是使用 observe() 还是 toObservable() 的执行方式:
observableExecutionMode 参数有如下两种可选值:
  • ObservableExecutionMode.EAGER :表示使用 observe() 执行方式(这个是默认值,即不设置此参数时就是默认使用该方式)
  • ObservableExecutionMode.LAZY :表示使用 toObservable() 的执行方式
@Service
public class HelloService {

    @Autowired
    RestTemplate restTemplate;

    //使用observe()执行方式
    @HystrixCommand
    public Observable<String> hello1() {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if(!subscriber.isUnsubscribed()) {
                        String result = restTemplate.getForEntity("http://HELLO-SERVICE/hello",
                                String.class)
                                .getBody();
                        subscriber.onNext(result);
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        });
    }

    //使用toObservable()执行方式
    @HystrixCommand(observableExecutionMode = ObservableExecutionMode.LAZY)
    public Observable<String> hello2() {
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                try {
                    if(!subscriber.isUnsubscribed()) {
                        String result = restTemplate.getForEntity("http://HELLO-SERVICE/hello",
                                String.class)
                                .getBody();
                        subscriber.onNext(result);
                        subscriber.onCompleted();
                    }
                } catch (Exception e) {
                    subscriber.onError(e);
                }
            }
        });
    }
}

(2)我们可以通过如下方式进行订阅:
@RestController
public class ConsumerController {
    @Autowired
    HelloService helloService;

    @GetMapping("/hello-consumer")
    public String helloConsumer() {
        helloService.hello1().subscribe((v) ->{
            System.out.println("hello1:" + v);
        });
        helloService.hello2().subscribe((v) ->{
            System.out.println("hello2:" + v);
        });
        return "";
    }
}

(3)observe() toObservable() 虽然都返回了 Observable,但是它们略有不同,区别在于命令是否必须订阅后才会执行命令:
  • observe() 返回的是一个 Hot Observable,该命令会在 observe() 调用的时候立即执行,当 Observable 每次被订阅的时候会重放它的行为。
  • toObservable() 返回的是一个 Cold ObservabletoObservable() 执行之后,命令不会被立即执行,只有当所有订阅者都订阅它之后才会执行。
@RestController
public class ConsumerController {
    @Autowired
    HelloService helloService;

    @GetMapping("/hello-consumer")
    public String helloConsumer() {
        helloService.hello1(); // 即使没有订阅也会执行命令(发起请求)
        helloService.hello2(); // 不会执行命令 
        return "";
    }
}
评论0