SpringCloud - 服务容错保护组件Hystrix的使用详解2(创建请求命令)
作者:hangge | 2020-07-13 08:10
二、创建请求命令
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() 的执行方式:
(2)我们可以通过如下方式进行订阅:
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 Observable,toObservable() 执行之后,命令不会被立即执行,只有当所有订阅者都订阅它之后才会执行。
@RestController
public class ConsumerController {
@Autowired
HelloService helloService;
@GetMapping("/hello-consumer")
public String helloConsumer() {
helloService.hello1(); // 即使没有订阅也会执行命令(发起请求)
helloService.hello2(); // 不会执行命令
return "";
}
}
全部评论(0)