基础篇——Spring Cloud Hystrix

一、Hystrix使用之创建请求命令

  继承HystrixCommand:

public class UserCommand extends HystrixCommand<User> {

    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() {
        return restTemplate.getForObject("http://USER-SERVICE/user?id={1}",     
        User.class, id);
    }
}

  注:同步执行,User user = new UserCommand(restTemplate, 1L).execute();

    异步执行,Future<User> futureUser = new UserCommand(restTemplate, 1L).queue();

    Hot Observable,Observable<String> ho = new UserCommand(restTemplate, 1L).observe();

    Cold Observable,Observable<String> go = new UserCommand(restTemplate, 1L).toObservable();

  注解@HystrixCommand实现同步执行:

public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand
    public User getUserById(Long id) {
        return restTemplate.getForObject("http://USER-SERVICE/user?id={1}", 
        User.class, id);
    }
}

  注解@HystrixCommand实现异步执行:

public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand
    public Future<User> getUserByIdAsync(final String id) {
        return new AsyncResult<User>() {
            @Override
            public User invoke() {
                return restTemplate.getForObject("http://USER-SERVICE/user?id= 
                {1}", User.class, id);
            }
        };
    }
}

  继承HystrixObservableCommand:

public class UserObservableCommand extends HystrixObservableCommand<User> {

    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<User> construct() {
        return Observable.create(new Observable.OnSubscribe<User>(){
            @Override
            public void call(Subscribe<? super User> observable) {
                try {
                    if (!observable.isSubscribed()) {
                        User user = restTemplate.getForObject("http://USER-SERVICE/user?id={1}", User.class, id);
                        observable.onNext(user);
                        observable.onCompleted();
                    }
                } catch (Exception e) {
                    observable.onError(e);
                }
            }
        });
    }
}

  注解@HystrixCommand实现响应式命令:

public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand
    public Observable<User> getUserById(final String id) {
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscribe<? super User> observable) {
                try {
                    if (!observable.isSubscribe()) {
                        User user = restTemplate.getForObject("http://USER-SERVICE/user?id={1}", User.class, id);
                        observable.onNest(user);
                        observable.onCompleted();
                    }
                } catch (Exception e) {
                    observable.onError(e);
                }
            }
        });
    }
}

二、定义服务降级

  对于有返回值的服务,也就是说调用者需要请求服务获取到某些有用的信息,如果在HystrixCommand或HystrixObservableCommand执行出现错误、超时、线程池拒绝、断路器熔断等情况,需要进行服务降级处理来保障调用者的体验。对于继承HystrixCommand执行请求服务,需要重写getFallBack方法;

public class UserCommand extends HystrixCommand<User> {

    @Override
    protected User getFallBack() {
        return new User();
    }
}

  对于继承HystrixObservableCommand执行请求服务,需要重写resumeWithFallBack方法;

public class UserObservableCommand extends HystrixObservableCommand<User> {

    @Override
    protected User resumeWithFallBack() {
        return new User();
    }
}

  对于注解@HystrixCommand执行请求服务,需要使用属性fallBackMethod="方法名",且“方法名”必须在同一类中;

public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallBackMethod="defaultUserById")
    public Observable<User> getUserById(final String id) {
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscribe<? super User> observable) {
                try {
                    if (!observable.isSubscribe()) {
                        User user = restTemplate.getForObject("http://USER-SERVICE/user?id={1}", User.class, id);
                        observable.onNest(user);
                        observable.onCompleted();
                    }
                } catch (Exception e) {
                    observable.onError(e);
                }
            }
        });
    }

    protected User defaultUserById() {
        return new User();
    }
}

  当然对于一些不需要服务返回必须有用信息的请求,可以选择不使用服务降级处理,可以直接将错误信息返回给调用者即可。例如:使用HystrixCommand请求写操作的服务,如果写入不成功,直接将错误返回给调用者,通知其稍后重试即可。

三、异常处理

  Hystrix执行请求服务的异常有两种,HystrixBadRequestException和其他。因为服务降级策略的存在,除了由HystrixBadRequestException包装的异常外,其他的所有异常都会触发服务降级策略。注解@HystrixCommand通过属性ignoreExceptions实现指定异常向HystrixBadRequestException的包装,当服务请求出现指定异常时,不触发服务降级策略。

  当发生服务降级时,获取详细的异常服务,在继承类HystrixCommand或HystrixObserableCommand中,通过其父类方法getExecutionException获得;

    @Override
    protected User getFallBack() {
        Throwable e = getExecutionException();
        return new User();
    }

  注解@HystrixCommand属性fallBackMethod指定方法中接收参数Throwable e;

    protected User defaultUserById(Throwable e) {
        return new User();
    }

四、命令名称、分组以及线程池划分

  分组、命令名称和线程池划分是Hystrix对服务请求的细粒化分配,即此次服务请求被分配到某组某个线程池的某个命令,能够更好的统计和分配,在继承方式中设置组名、命令名称和划分的线程池名称;

    public UserCommand(RestTemplate restTemplate, Long id) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GroupName"))
                .andCommandKey(HystrixCommandKey.Factory.asKey("CommandName"))
                .andThreadPoolKey(HystrixCommandThreadPoolKey.Factory.asKey("ThreadPoolKey")));
        this.restTemplate = restTemplate;
        this.id = id;
    }

  注解@HystrixCommand通过属性groupKey、commandKey、threadPoolKey来设置服务请求的组、命令和线程池划分;

    @HystrixCommand(fallBackMethod="defaultUserById", groupKey="UserGroup", commandKey="getUserById", threadPoolKey="userThreadPool")
    public Observable<User> getUserById(final String id) {
        return Observable.create(new Observable.OnSubscribe<User>() {
            @Override
            public void call(Subscribe<? super User> observable) {
                try {
                    if (!observable.isSubscribe()) {
                        User user = restTemplate.getForObject("http://USER-SERVICE/user?id={1}", User.class, id);
                        observable.onNest(user);
                        observable.onCompleted();
                    }
                } catch (Exception e) {
                    observable.onError(e);
                }
            }
        });
    }
posted @ 2020-08-12 15:46  不浪小生  阅读(205)  评论(0编辑  收藏  举报