Hystrix选择线程池策略实现资源隔离
这是我参与更文挑战的第4天,活动详情查看: 更文挑战
上一篇文章-【SpringCloud系列】- Hystrix选择线程池策略实现资源隔离(1) 介绍Hystrix选择线程池策略实现资源隔离的设置、线程池关键参数,接下来利用HystrixCommand获取单个用户数据
思路
将调用会员服务的操作封装在HystrixCommand中,限定一个key,比如UserInfoCommandGroup,每次调用会员服务,就只会用该线程池中的资源,不会再使用其他线程资源
使用HystrixCommand获取单条数据
public class UserInfoCommand extends HystrixCommand<UserOutpDTO> {
private Long userId;
public UserInfoCommand(Long userId){
super(HystrixCommandGroupKey.Factory.asKey("UserInfoCommandGroup"));
this.userId =userId;
}
@Override
protected UserOutpDTO run() throws Exception {
String url = "localhost:8080/user/info?userId="+userId;
String result = HttpClientUtil.sendGetRequest(url);
return JSONObject.parseObject(result,UserOutpDTO.class);
}
}
在缓存服务接口中,根据userId 创建command并执行,获取到用户数据
@Controller
@Slf4j
public class UserController {
@GetMapping("getUserInfo")
public String getUserInfo(Long userId){
UserInfoCommand userInfoCommand = new UserInfoCommand(userId);
UserOutpDTO userOutpDTO = userInfoCommand.execute();
return "success";
}
}
注意:HystrixCommand执行execute()方法是同步
HystrixCommand能否批量获取数据?
不能,但是可使用HystrixObservableCommand批量获取数据,获取用户数据,全部都绑定到同一个线程池,通过HystrixObservableCommand的线程池核心线程去执行,而在线程池中核心线程批量处理多个userId的userInfo获取结果集
public class UserInfosCommand extends HystrixObservableCommand<UserOutpDTO> {
private String[] userIds;
public UserInfosCommand(String[] userIds){
super(HystrixCommandGroupKey.Factory.asKey("UserInfosCommand"));
this.userIds=userIds;
}
@Override
protected Observable<UserOutpDTO> construct() {
return Observable.unsafeCreate((Observable.OnSubscribe<UserOutpDTO>) subscriber->{
for (String userId:userIds) {
String url="localhost:8080/user/info?userId="+userId;
String result = HttpClientUtil.sendGetRequest(url);
UserOutpDTO userOutpDTO = JSONObject.parseObject(result, UserOutpDTO.class);
subscriber.onNext(userOutpDTO);
}
subscriber.onCompleted();
}).subscribeOn(Schedulers.io());
}
}
根据传来的id列表,比如以“,”分隔的userId字符串,通过HystrixObservableCommand,执行Hystrix的一些API方法,获取所有用户数据
@GetMapping("getUserInfos")
public String getUserInfos(String userIds){
String[] userIdArr = userIds.split(",");
UserInfosCommand userInfosCommand = new UserInfosCommand(userIdArr);
Observable<UserOutpDTO> userInfos = userInfosCommand.observe();
userInfos.subscribe(new Observer<UserOutpDTO>() {
@Override
public void onCompleted() {
log.info("完成获取所有用户信息!");
}
@Override
public void onError(Throwable throwable) {
log.error(throwable.getMessage());
}
@Override
public void onNext(UserOutpDTO userOutpDTO) {
log.info("userOutpDTO:{}",userOutpDTO);
}
});
return "success";
}
总结
Hystrix选择线程池策略实现资源隔离,线程池默认的线程大小是10个,最多就只有10个线程去调用会员服务的接口。即使会员服务接口故障了,最多只有10个线程会阻塞在调用会员服务接口,而tomcat内其他线程还可调用其他服务,执行其他的任务,达到资源隔离的目的。