This book, is definitely among one of the best books, I've read this year. It lays out some critical aspects to creating and rolling out stable software systems. Each of the case studies discussed is based on real events.
While reading the book you will feel, how nice it would be if there is a library you could use to gain the advantages discussed to make your programs/software/systems rock solid.
The JRugged is such a library written to be used in Java. To summarize, what it offers , here it is (directly from the project home page) :-
The jrugged library provides straightforward add-ons to existing code to make it more robust and easier to manage.
Although there are several lower-level building block classes here available for custom solutions, most clients will find they can use just the following classes:
CircuitBreaker provides a way to wrap a service in a way that provides a bulkhead against system failure; when a remote service fails, further calls to the service are prevented for a period of time to allow the remote service to recover.
Initializer provides a way to decouple service construction from initialization/startup and allows the latter to occur in the background, even retrying if initial attempts to initialize fail.
PerformanceMonitor provides a way to wrap a service and collect a series of useful statistics about its latency and throughput, even calculating moving averages across different time windows.
Monitorable, Status, and RolledUpStatus are related classes that provide a simple RED/YELLOW/GREEN encoding for service health, possibly useful for constructing operational dashboards.
Generally speaking, most of these classes implement a ServiceWrapper interface to allow them to be applied around existing services using the Decorator design pattern. Those classes providing operational information, such as PerformanceMonitor and Monitorable can be wrapped in classes that expose their data to JMX controls or on web-accessible health status pages as desired.
Here I would show you, how easy it to use this in your existing code base. It provides it by the classic use of the Decorator Pattern.
import org.fishwife.jrugged.CircuitBreaker;
import org.fishwife.jrugged.PerformanceMonitor;
import org.fishwife.jrugged.Status;
import org.springframework.jmx.export.annotation.ManagedAttribute;
public abstract class AbstractMonitor implements IMonitorable {
/** Circuit breaker to detect server oveloading */
protected final CircuitBreaker cBreaker = new CircuitBreaker();
/** Performance stat monitor */
protected final PerformanceMonitor perfMonitor = new PerformanceMonitor(5);
@ManagedAttribute(description = "My System status")
public String getHealthCheck() {
return cBreaker.getStatus().getSignal();
}
@ManagedAttribute
public double getAverageFailureLatencyLastDay() {
return perfMonitor.getAverageFailureLatencyLastDay();
}
@ManagedAttribute
public double getAverageFailureLatencyLastHour() {
return perfMonitor.getAverageFailureLatencyLastHour();
}
@ManagedAttribute
public double getAverageFailureLatencyLastMinute() {
return perfMonitor.getAverageFailureLatencyLastMinute();
}
@ManagedAttribute
public double getAverageSuccessLatencyLastDay() {
return perfMonitor.getAverageSuccessLatencyLastDay();
}
@ManagedAttribute
public double getAverageSuccessLatencyLastHour() {
return perfMonitor.getAverageSuccessLatencyLastHour();
}
@ManagedAttribute
public double getAverageSuccessLatencyLastMinute() {
return perfMonitor.getAverageSuccessLatencyLastMinute();
}
@ManagedAttribute
public long getFailureCount() {
return perfMonitor.getFailureCount();
}
@ManagedAttribute
public double getFailureRateLastDay() {
return perfMonitor.getFailureRateLastDay();
}
@ManagedAttribute
public double getFailureRateLastHour() {
return perfMonitor.getFailureRateLastHour();
}
@ManagedAttribute
public double getFailureRateLastMinute() {
return perfMonitor.getFailureRateLastMinute();
}
@ManagedAttribute
public double getFailureRateLifetime() {
return perfMonitor.getFailureRateLifetime();
}
@ManagedAttribute
public long getRequestCount() {
return perfMonitor.getRequestCount();
}
@ManagedAttribute
public double getRequestRateLastDay() {
return perfMonitor.getRequestRateLastDay();
}
@ManagedAttribute
public double getRequestRateLastHour() {
return perfMonitor.getRequestRateLastHour();
}
@ManagedAttribute
public double getRequestRateLastMinute() {
return perfMonitor.getRequestRateLastMinute();
}
@ManagedAttribute
public double getRequestRateLifetime() {
return perfMonitor.getRequestRateLifetime();
}
@ManagedAttribute
public long getSuccessCount() {
return perfMonitor.getSuccessCount();
}
@ManagedAttribute
public double getSuccessRateLastDay() {
return perfMonitor.getSuccessRateLastDay();
}
@ManagedAttribute
public double getSuccessRateLastHour() {
return perfMonitor.getSuccessRateLastHour();
}
@ManagedAttribute
public double getSuccessRateLastMinute() {
return perfMonitor.getSuccessRateLastMinute();
}
@ManagedAttribute
public double getSuccessRateLifetime() {
return perfMonitor.getSuccessRateLifetime();
}
public CircuitBreaker getCBreaker() {
return cBreaker;
}
public PerformanceMonitor getPerfMonitor() {
return perfMonitor;
}
public Status getStatus (){
return cBreaker.getStatus();
}
}
Now, your class just needs to extend this abstract class inherits all those JMX statistics as well as the handles to the Circuitbreaker and PerformanceMonitor Object.
@ManagedResource(objectName = "com.example:type=manager,name=mysystem",
description = "shows the running status of mysystem")
public class MySystem extends AbstractMonitor {
.........
.........
//This is the method I want to decorate
public BackEndData processArgument(final String myArg) {
final BackEndService theBackend = backend;
try {
return cBreaker.invoke(new Callable< BackEndData >() {
public BackEndData call() throws Exception {
return perfMonitor.invoke(new Callable< BackEndData >() {
//This is the actual method which you were using earlier without decoration
public BackEndData call() throws Exception {
return theBackend.processArgument(myArg);
}
});
}
});
} catch (RuntimeException re) {
throw re;
} catch (Exception e) {
throw new RuntimeException("wrapped", e);
}
}
}
You probably would change this code a little bit depending on the definitions of your critical components, and the health status (But you get the idea).
Now just fire up the JConsole and you can see all the statistics for your classes. And it handles failures as well, showing you the status of the system as Green/Red/Yellow (depending on your definition of the critical system/components).
Please check it out for details, as the code base is pretty terse.
You may wish to extend it to be used as an Aspect (AOP), so that your classes could avail the benefits without changing your java code. The project mentions, it is looking to offer AOP wrapper to make it easier to do drop-in decoration of existing code.
So wait if you could or if you implement it yourself, please post it so others could use it.
2 comments:
You have me sold -- been meaning to read this book -- will definitely do so. Often many design books do not take into account the practical realities of day-to-day management. It seems this book and jrugged provides such opportunities.
Thanks for the writeup Anshu! I had thought about the AbstractMonitor class you had, but wasn't sure that the JMX attributes would be inherited correctly. That's great!
Also, I will note that some other folks here at CIM have made some extensions to support Spring-AOP, so we'll be rolling that into an upcoming jrugged release.
Post a Comment