The project uses SpringBoot(2.3.4)
and SpringCloud(Hoxton.SR8)
.
There are three classes: BillController, BillService(interface) and BillServiceImpl (implements BillService), BillController calls function getBillList
declared in BillService.
In BillServiceImpl, there are two method, one is getBillList
, the other is simulateUnstableService
, getBillList
calls simulateUnstableService
, and in simulateUnstableService
just a long sleep(2000).
The strange thing is that if I annoate getBillList
with HystrixCommand
, then it works as I expect. But if I move HystrixCommand
to annoate simulateUnstableService
, then there is no break which means timeout does not trigger Circuit Breaker
.
@Service
public class BillServiceImpl implements BillService {
@Override
// have effact
@HystrixCommand(
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
}
)
public List<Bill> getBillList(long userId) {
return simulateUnstableService(userId);
}
// no effact
// @HystrixCommand(
// commandProperties = {
// @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
// }
// )
public List<Bill> simulateUnstableService(long userId) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new ArrayList<>();
}
}
And more, if I just copy simulateUnstableService
method content to getBillList
, and annoate getBillList with HystrixCommand, the breaker also works.
Why?
Excellent question.
Hystrix uses AOP to wrap the method being called and deliver the Circuit Braking functionality. There is actually an aspect class
HystrixCommandAspect.java
which defines the around advice used to achieve this.Now, AOPs don't exactly work if you call a method from within a class. See this answer for more clarity- Spring AOP not working for method call inside another method