【SpringCloud系列】- Hystrix选择线程池策略实现资源隔离(2)

583 阅读2分钟

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内其他线程还可调用其他服务,执行其他的任务,达到资源隔离的目的。