Đội ngũ netflix-hystrix đã phát triển hystrix-javanica, sử dụng các annotation Java phổ biến và lập trình hàm, để thay thế phương pháp lập trình nhàm chán của hystrix.
Điểm chính là việc sử dụng annotation @HystrixCommand.
/**
* Thực thi đồng bộ
*/
@HystrixCommand(fallback="syncFallback")
public List<NguoiDung> timNguoiDung(NguoiDung thamSo){
return nguoiDungRepository.timKiem(thamSo);
}
/**
* Thực thi không đồng bộ
*/
@HystrixCommand(fallback="asyncFallback")
public Future<List<NguoiDung>> timNguoiDung(NguoiDung thamSo){
return new AsyncResult<List<NguoiDung>>(){
public List<NguoiDung> goiThucThi() {
return nguoiDungRepository.timKiem(thamSo);
}
};
}
Future<List<NguoiDung>> ketQua = nguoiDungService.timNguoiDung(thamSo);
List<NguoiDung> danhSach = ketQua.get();
/**
* Thực thi Reactive
*/
@HystrixCommand
public Observable<List<NguoiDung>> timNguoiDung(NguoiDung thamSo){
return Observable.create(nhanVienPhatSinh ->{
if(!nhanVienPhatSinh.isUnscribed()){
nhanVienPhatSinh.onNext(nguoiDungRepository.timKiem(thamSo));
nhanVienPhatSinh.onCompleted();
}
});
}
Observable quanSat = nguoiDungService.timNguoiDung(thamSo);
List<NguoiDung> danhSach = quanSat.toBlocking().single();
Tham số của phương thức fallback phải khớp với phương thức được thực thi, nếu không hystrix sẽ không tìm thấy phương thức fallback và sẽ ném ra ngoại lệ trực tiếp.
Phương thức fallback cũng có thể thực thi đồng bộ hoặc không đồng bộ.
/**
* Fallback cho phương thức đồng bộ
*/
@HystrixCommand(fallback="defaultFallback")
private List<NguoiDung> syncFallback(NguoiDung thamSo){
return Lists.newArrayList(new NguoiDung("Tran Van A", 25));
}
/**
* Fallback cho phương thức không đồng bộ
* Tham số Throwable là tùy chọn
*/
@HystrixCommand(fallback="defaultFallback")
private Future<List<NguoiDung>> asyncFallback(NguoiDung thamSo, Throwable loi){
return new AsyncResult<List<NguoiDung>>(){
public List<NguoiDung> goiThucThi() {
return Lists.newArrayList(new NguoiDung("mac dinh", 22));
}
};
}
Phương thức fallback cũng có thể bị fallback.
private List<NguoiDung> defaultFallback(NguoiDung thamSo){
return null;
}
Nguồn tham khảo: https://github.com/Netflix/Hystrix/wiki/How-To-Use#CommandName
https://github.com/Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica
Quy trình thực thi Hystrix Command
- HystrixCommand có ba phương thức thực thi: đồng bộ, không đồng bộ và thực thi Reactive.
- Hystrix sẽ chọn phương thức đã được thiết lập trước để thực thi HystrixCommand.
- Nếu bạn sử dụng Request Cache và phản hồi của yêu cầu này có trong cache, phản hồi sẽ được trả về ngay lập tức dưới dạng Observable.
- Nếu bộ ngắt mạch (circuit breaker) ở trạng thái mở, HystrixCommand sẽ không được thực thi mà sẽ thực thi phương thức fallback.
- Nếu pool thread, hàng đợi hoặc semaphore của Hystrix bị đầy, HystrixCommand sẽ không được thực thi mà sẽ thực thi phương thức fallback.
- Thực thi logic nghiệp vụ đã được viết. Kiểm tra xem thực thi có thành công không, có bị timeout không. Nếu logic nghiệp vụ không ném ra ngoại lệ và không bị timeout, kết quả thực thi thành công sẽ được trả về.
- Nếu thực thi thất bại hoặc bị timeout, cần áp dụng chiến lược fallback của Hystrix và báo cáo cho bộ ngắt mạch để thống kê và tính toán trạng thái của nó.
- Từ quy trình trên, có thể tóm tắt các nguyên nhân chính khiến Hystrix kích hoạt chiến lược fallback: logic nghiệp vụ ném ra ngoại lệ không phải HystrixBadRequestException, logic nghiệp vụ thực thi bị timeout, bộ ngắt mạch mở chặn trực tiếp, và pool thread/semaphore bị đầy từ chối trực tiếp.
- Khi một HystrixCommand không có chiến lược fallback, nó sẽ ném ra ngoại lệ trực tiếp.
- Nếu logic fallback thất bại, nó sẽ ném ra ngoại lệ trực tiếp hoặc thực thi logic fallback của fallback.
- Thực thi thành công, trả về kết quả thực thi thành công. Đối với kết quả thực thi thành công, Hystrix có chiến lược thực thi như sau:
Sau khi thực thi thành công, một đối tượng Observable sẽ được trả về, sau đó dựa trên chiến lược thực thi đã được thiết lập, kết quả sẽ được trả về.
HystrixCommand mở một bộ ngắt mạch như thế nào?
HystrixCommand sử dụng bốn tham số để xác định có cần mở bộ ngắt mạch không:
- circuitBreakerRequestVolumeThreshold
- metricsRollingStatisticalWindowBuckets
- metricsRollingStatisticalWindow
- circuitBreakerErrorThresholdPercentage
Mỗi bộ ngắt mạch của HystrixCommand mặc định duy trì 10 bucket, được thiết lập qua tham số metricsRollingStatisticalWindowBuckets.
Giá trị mặc định của metricsRollingStatisticalWindow là 10 giây, mỗi bucket được phân bổ 1 giây.
Giá trị mặc định của circuitBreakerRequestVolumeThreshold là 20.
Nghĩa là trong 10 giây, phải có ít nhất 20 yêu cầu thất bại, timeout hoặc bị từ chối bởi pool thread/semaphore để kích hoạt bộ ngắt mạch.
Tham số circuitBreakerErrorThresholdPercentage là ngưỡng tỷ lệ phần trăm thất bại. Nếu tỷ lệ thất bại vượt qua ngưỡng này, bộ ngắt mạch sẽ được mở.
HystrixCommand đóng một bộ ngắt mạch như thế nào?
Sau khi bộ ngắt mạch mở trong một khoảng thời gian, nó sẽ chuyển sang trạng thái bán mở (Half-Open State). Khoảng thời gian này được thiết lập qua tham số circuitBreakerSleepWindowInMilliseconds.
Khi một yêu cầu đi qua bộ ngắt mạch trong trạng thái này, bộ ngắt mạch sẽ không chặn yêu cầu mà sẽ cho yêu cầu đi qua. Nếu yêu cầu này vẫn thất bại, bộ ngắt mạch sẽ chuyển về trạng thái mở.
Nếu yêu cầu này thành công, bộ ngắt mạch sẽ đóng lại và bắt đầu thống kê lần tiếp theo.