Spring Could Hystrix 使用詳細

目錄

介紹

注: pom.xml和application.properties鍵“服務容錯保護:Spring Could Hystrix”

1 請求命令的創建

1.1 未使用@HystrixCommand註解形式

Hystrix創建通過繼承HystrixCommand類來實現。getFallback()方法定義降級錯誤返回。

public class UserCommand extends HystrixCommand<User> {
    @Autowired
    private RestTemplate restTemplate;

    public UserCommand() {
        super(HystrixCommandGroupKey.Factory.asKey("UserCommand"));
    }

    @Override
    protected User run() throws Exception {
        System.out.println("");
        return  restTemplate.getForObject("http://hello-service/user/login",User.class);
    }

    @Override
    protected User getFallback() {
        System.out.println("==================================");
        System.out.println(getFailedExecutionException().getMessage());
        return new User("def","def");
    }
}

測試:

1 同步執行:User u = new UserCommand().execute()
2 異步執行:Future<User> fWorld = new UserCommand().queue();
3 通過:Observable實現響應   
Observable<User> observe = new UserCommand().observe();
Observable<User> userObservable = new UserCommand().toObservable();

1.2 使用@HystrixCommand註解

@Service("userService")
public class UserService {
    /**獲取logger實例*/
    private final Logger logger = Logger.getLogger(getClass().toString());

    @Autowired
    private RestTemplate restTemplate;

    /**
     *同步調用
     * @return
     */
    @HystrixCommand(fallbackMethod = "notFindFallback1")
    public String login()
    {
        logger.info("調用:http://hello-service/user/login");
       // ResponseEntity<String> forEntity = restTemplate.getForEntity("http://hello-service/user/login", String.class);
        String forObject = restTemplate.getForObject("http://hello-service/user/login", String.class);
        return "我是一個消費者去調用==》"+forObject;
    }


    /**
     *異步調用
     * @return
     */
    @HystrixCommand(fallbackMethod = "notFindFallback")
    public Future<String> loginAsync()
    {
        return new AsyncResult<String>() {
            @Override
            public String invoke() {
                String forObject = restTemplate.getForObject("http://hello-service/user/login", String.class);
                return "我是一個消費者去調用==》"+forObject;
            }
        };
    }

    /**
     * 異常觸發方法
     * @return
     */
    public String notFindFallback()
    {
        return "error";
    }

    /**
     * 異常捕獲方法,可捕獲異常
     * @return
     */
    public String notFindFallback1(Throwable e)
    {
        return e.getMessage();
    }
}

@HystrixCommand註解屬性

1 fallbackMethod指定異常降級方法
2 observableExecutionMode = ObservableExecutionMode.EAGER表示.observe()執行方式observableExecutionMode = ObservableExecutionMode.LAYZ表示.toObservable();
3 ignoreExceptions 指定某類異常觸發時,不走fallbackMethod降級方法
4 commandKey 指定命名名,groupKey指定組名,threadPoolKey指定線程。用於劃分Hystrix分組,默認同組名化一個線程池組。所以需要指定線程劃分。(setter設置)

注:一些情況不需要做降級處理。如寫操作,批處理或者離線計算。(操作的返回一般爲void

2 請求緩存

Hystrix提供請求緩存,減輕高併發情況下服務的壓力。

2.1 通過重寫getCache()方法

繼承HystrixCommand類,重寫getCacheKey()方法。getCache()方法返回緩存key值。
清理緩存使用HystrixRequestCache.clear()。(getCacheKey()默認返回null,緩存未開啓)

2.2 使用緩存註解(必須配合@HystrixCommand使用)

@CacheResult標記結果加入緩存
@CacheRemove請求緩存失效
@CacheKey標記緩存的key

2.2.1 使用@CacheResult實現緩存功能

@CacheResult(cacheKeyMethod = "getCacheKey")
@HystrixCommand(commandKey = "findUserById", groupKey = "UserService", threadPoolKey = "userServiceThreadPool")
public UserVO findById(Long id) {
    ResponseEntity<UserVO> user = restTemplate.getForEntity("http://users-service/user?id={id}", UserVO.class, id);
    return user.getBody();
}

public String getCacheKey(Long id) {
    return String.valueOf(id);
}

2.2.2 使用@CacheResult和@CacheKey實現緩存功能

@CacheResult
@HystrixCommand(commandKey = "findUserById", groupKey = "UserService", threadPoolKey = "userServiceThreadPool")
public UserVO findById2(@CacheKey("id") Long id) {
    ResponseEntity<UserVO> user = restTemplate.getForEntity("http://users-service/user?id={id}", UserVO.class, id);
    return user.getBody();
}

2.2.3 使用@CacheRemove清空緩存

@CacheRemove(commandKey = "findUserById")
@HystrixCommand(commandKey = "updateUser",groupKey = "UserService",threadPoolKey = "userServiceThreadPool")
public void updateUser(@CacheKey("id")UserVO user){
    restTemplate.postForObject("http://users-service/user",user,UserVO.class);
}

請求合併

2 總結

參考:

1 《Spring Could 微服務實戰》 翟永超 電子工業出版社 2017.5

參考網站:http://blog.didispace.com/Spring-Cloud基礎教程/
        https://springcloud.cc
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章