Base on part 1, today i’m going to implement circuit-breaker pattern with java. A few functions i will to perform as follows
- Use breaker pattern to build acts proxy for service remote call.
- Support config timeout and number of retry to execute command.
- Compatible with multiple threads model.
- Inheritance and flexibility.
- Demo run with simple application.
UML for core implement Breaker pattern
BreakerExecute.java is main class implement proxy acts for remote call
+ Return fail when state of service is OPEN
if (state == BreakerState.OPEN)
{
try {
error(new BreakerRejectException(), null);
commandQueues.add(currentCommand);
continue;
}
catch (Exception errHandle) {
LOGGER.error(errHandle, errHandle);
}
}
+ Change state to CLOSE when have a remote call is successful
currentCommand.run();
if (state == BreakerState.HALF_OPEN) {
state = BreakerState.CLOSE;
numberFailure.set(0);
}
+ Retry execute command with number of re-invoke is limited
Integer counter = mapRetryCommand.get(currentCommand.getId());
if(counter == null){
counter = 1;
mapRetryCommand.put(currentCommand.getId(), counter);
}
if (counter < numberAttempts) {
commandQueues.add(currentCommand);
counter++;
mapRetryCommand.put(currentCommand.getId(), counter);
} else {
mapRetryCommand.remove(currentCommand.getId());
try {
error(new BreakerExpiredException(), currentCommand);
} catch (Exception errHandle) {
LOGGER.error(errHandle, errHandle);
}
+ Change state CLOSE to OPEN when the number of recent failure exceed a specified threshold.
if (state == BreakerState.CLOSE) {
if (numberFailure.incrementAndGet() > limitFailure) {
state = BreakerState.OPEN;
TIMER.newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
state = BreakerState.HALF_OPEN;
}
}, timeout, TimeUnit.MILLISECONDS);
}
Demo: Suppose, i have cluster with 2 server (A, B) and Server A will invoke addProduct() to B by remote call. Here i will implement circuit-breaker on A to manage invoke remote call to B.
+ AddProductCommand is extended BreakerCommand
public class AddProductCommand extends BreakerCommand{
private static Logger LOGGER = Logger.getLogger(AddProductCommand.class);
private Product product;
@Override
public void run() {
LOGGER.info("Process product "+product.getName());
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
+ ProductService is extended BreakerExecute and add AddProductCommand to execute
public class ProductService extends BreakerExecute{
private static Logger LOGGER = Logger.getLogger(ProductService.class);
--more--
public void addProduct(Product product){
AddProductCommand command = new AddProductCommand();
command.setProduct(product);
putCommand(command);
}
--more--
}
In the next post i will implement circuit-pattern by Golang. Please contact to me or comment into this below about your opinion about post, thank you for watching.
Get more project : source code