March 20, 2011

Jolokia + Highcharts = JMX for human beings

Java Management Extensions (JMX) is a well established, but not widespread technology allowing to monitor and manage every JVM. It provides tons of useful information, like CPU, thread and memory monitoring. Also every application can register its own metrics and operations in so called MBeanServer. Several libraries take advantage of JMX: Hibernate, EhCache and Logback and servers like Tomcat or Mule ESB, to name a few. This way one can monitor ORM performance, HTTP worker threads utilization, but also change logging levels, flush caches, etc. If you are creating your own library or container, JMX is a standard for monitoring, so please don't reinvent a wheel. Also Spring has a wonderful support for JMX.

If this standard is so wonderful, why aren't we using it all day long? Well, history of JMX reaches the dark ages of J2EE. Although the specification isn't that complicated, there are at least two disadvantages of JMX effectively discouraging people from using it. First one lies on the server side. At the foundation of Java Management Extensions is an MBeanServer where you register MBeans. Each MBean exposes its properties (attributes) and operations for external access. This is fine (especially when Spring is used: 1 line of XML + two annotations), but there's a catch. By default the MBeanServer exposes itself via RMI, which is certainly not the top XXI century protocol...

The second drawback of JMX lies on the client side. JConsole, although not terrible, has very limited functionality. If we want to present our JMX-enabled application to the customer, showing JConsole as a client is a bit embarrassing. It is capable of showing graphs, but you cannot display more than one attribute at the same composite graph and you also can't observe attributes from different MBeans at the same time. Last but not least, again, we're living in the XXI century, Swing client? Weird RMI port? What about Web 2.0 rave? Knowing how much I love charts (and how data visualization is important for diagnosing and correlating facts) I felt really disappointed by JConsole capabilites. And the only rival of JConsole seems dead.
Jolokia – bridge JMX over HTTP

I knew exactly what I wanted: HTTP transport for JMX server, so that I can easily access MBeanServer from outside without the RMI mess. Jolokia meets my expectations perfectly. This small library (about 170 kiB) connects to a given MBeanServer and exposes it via REST-like interface. Just deploy the jolokia.war file on your servlet container and use whatever HTTP client you want to monitor your JVM!

$ curl localhost:8080/jolokia
{
  "request" : { "type" : "version" },
  "status" : 200,
  "timestamp" : 1300561261,
  "value" : {
      "agent" : "0.83",
      "info" : {
          "product" : "tomcat",
          "vendor" : "Apache",
          "version" : "7.0.10"
        },
      "protocol" : "4.1"
    }
}


$ curl localhost:8080/jolokia/read/java.lang:type=Memory/HeapMemoryUsage
{
  "request" : {
      "attribute" : "HeapMemoryUsage",
      "mbean" : "java.lang:type=Memory",
      "type" : "read"
    },
  "status" : 200,
  "timestamp" : 1300561367,
  "value" : {
      "committed" : "169607168",
      "init" : "49404160",
      "max" : "702808064",
      "used" : "16635472"
    }
}



March 11, 2011

Tenfold increase in server throughput with Servlet 3.0 asynchronous processing


It is not a secret that Java servlet containers aren't particularly suited for handling large amount of concurrent users. Commonly established thread-per-request model effectively limits the number of concurrent connections to the number of concurrently running threads JVM can handle. And because every new thread introduces significant increase of memory footprint and CPU utilization (context switches), handling more than 100-200 concurrent connections seems like a ridiculous idea in Java. At least it was in pre-Servlet 3.0 era.

In this article we will write scalable and robust file download server with throttled speed limit. Second version, leveraging Servlet 3.0 asynchronous processing feature, will be able to handle ten times bigger load using even less threads. No additional hardware required, just few wise design decisions.

Token bucket algorithm
Building a file download servers we have to consciously manage are our resources, especially network bandwidth. We don't want a single client to consume the whole traffic, we might even want to throttle the download limit dynamically at runtime, based on user, time of the day, etc. - and of course everything happens during heavy load. Developers love reinventing the wheel, unfortunately all our requirements are already addressed by absurdly simple token bucket algorithm.

The explanation in Wikipedia is pretty good, but since we'll adjust the algorithm a bit for our needs, here's even simpler description. First there was a bucket. In this bucket there were uniform tokens. Each token is worth 20 kiB (I will be using real values from our application) of raw data. Every time a client ask for a file, the server tries to take one token from the bucket. If it succeeds, he sends 20 kiB to the client. Repeat last two sentences. What if the server fails to obtain the token because the bucket is already empty? He waits.

So where are the tokens coming from? Background process fill the bucket from time to time. Now it becomes clear. If this background process adds 100 new tokens every 100 ms (10 times per second), each worth 20 kiB, the server is capable of sending 20 MiB/s (100 times 20 kiB times 10) max, shared amongst all the clients. Of course if the bucket is full (1000 tokens), new tokens are ignored. This works amazingly well – if bucket is empty, clients are waiting for next bucket filling cycle; and by controlling the bucket capacity we can limit total bandwidth.

Enough of talking, our simplistic implementation of token bucket starts with an interface (whole source code is available on GitHub in global-bucket branch):