在上一篇的-負載均衡Robbin中,我們簡單講解到負債均衡的演算法和策略。負載均衡就是分發請求流量到不同的伺服器,以減小伺服器的壓力和訪問效率,但是當負載均衡的某個伺服器或是服務掛掉之後,那麼程式會出現問題麽?接下來Hystrix將會講解 1.1.簡介 Hystix,即熔斷器。 主頁:https:// ...
在上一篇的-負載均衡Robbin中,我們簡單講解到負債均衡的演算法和策略。負載均衡就是分發請求流量到不同的伺服器,以減小伺服器的壓力和訪問效率,但是當負載均衡的某個伺服器或是服務掛掉之後,那麼程式會出現問題麽?接下來Hystrix將會講解
1.1.簡介
Hystix,即熔斷器。
主頁:https://github.com/Netflix/Hystrix/
Hystix是Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程服務、第三方庫,防止出現級聯失敗。
正常工作的情況下,客戶端請求調用服務API介面:
當有服務出現異常時,直接進行失敗回滾,服務降級處理:
當服務繁忙時,如果服務出現異常,不是粗暴的直接報錯,而是返回一個友好的提示,雖然拒絕了用戶的訪問,但是會返回一個結果。
這就好比去買魚,平常超市買魚會額外贈送殺魚的服務。等到逢年過節,超時繁忙時,可能就不提供殺魚服務了,這就是服務的降級。
系統特別繁忙時,一些次要服務暫時中斷,優先保證主要服務的暢通,一切資源優先讓給主要服務來使用,在雙十一、618時,京東天貓都會採用這樣的策略。
1.3.1.引入依賴
首先在user-consumer中引入Hystix依賴:
@Component
public class UserDao {@Autowired
private RestTemplate restTemplate;private static final Logger logger = LoggerFactory.getLogger(UserDao.class);
@HystrixCommand(fallbackMethod = "queryUserByIdFallback")
public User queryUserById(Long id){
long begin = System.currentTimeMillis();
String url = "http://user-service/user/" + id;
User user = this.restTemplate.getForObject(url, User.class);
long end = System.currentTimeMillis();
// 記錄訪問用時:
logger.info("訪問用時:{}", end - begin);
return user;
}public User queryUserByIdFallback(Long id){
User user = new User();
user.setId(id);
user.setName("用戶信息查詢出現異常!");
return user;
}
}
-
-
為了方便查看熔斷的觸發時機,我們記錄請求訪問時間。
在原來的業務邏輯中調用這個DAO:
@Service
public class UserService {@Autowired
private UserDao userDao;public List<User> queryUserByIds(List<Long> ids) {
List<User> users = new ArrayList<>();
ids.forEach(id -> {
// 我們測試多次查詢,
users.add(this.userDao.queryUserById(id));
});
return users;
}
}
改造服務提供者,隨機休眠一段時間,以觸發熔斷:
@Service
public class UserService {@Autowired
private UserMapper userMapper;public User queryById(Long id) throws InterruptedException {
// 為了演示超時現象,我們在這裡然線程休眠,時間隨機 0~2000毫秒
Thread.sleep(new Random().nextInt(2000));
return this.userMapper.selectByPrimaryKey(id);
}
}
然後運行並查看日誌:
id為9、10、11的訪問時間分別是:
id為12的訪問時間:
因此,只有12是正常訪問,其它都會觸發熔斷,我們來查看結果:
1.3.5.優化
雖然熔斷實現了,但是我們的重試機制似乎沒有生效,是這樣嗎?
其實這裡是因為我們的Ribbon超時時間設置的是1000ms:
而Hystix的超時時間預設也是1000ms,因此重試機制沒有被觸發,而是先觸發了熔斷。
所以,Ribbon的超時時間一定要小於Hystix的超時時間。
我們可以通過hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
來設置Hystrix超時時間。
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 6000 # 設置hystrix的超時時間為6000ms