Introducing Netty-HTTP from Cask

Sreevatsan Raman is the Head of Engineering at Cask where he is driving the company's engineering initiatives. Prior to Cask, Sree designed and implemented big data infrastructure at Klout and Yahoo!

At Cask, we are passionate about software development and developer productivity. We build software that we’d want to use and most of the software we have built is a result of “scratching our own itch”. For instance we built a cluster provisioning system – Coopr – to make it easy to provision clusters for internal testing. Apache Twill was created to make it easy to run applications on YARN and Tephra is made to easily manage transactions on top of HBase. In this blog post we will take a look at one such project called netty-http that we built to make it easy to write and manage HTTP services.

The motivation for netty-http

We expose all of CDAP’s functionality via HTTP based ReST APIs, for example: deploying CDAP applications, starting/stopping CDAP programs, ingesting data and the like. We chose Netty as a framework to build out the HTTP services because it allows writing fast, non-blocking, asynchronous services. While we were able to build powerful netty-based HTTP services, it soon became hairy to manage the code that maps HTTP end-points to the methods that handle the requests. The code base to manage the path routing looked something like:

The above code fragment, as you can imagine, has the following disadvantages

  1. Adding a new HTTP end-point could be very error prone
  2. The developer who wants to add an HTTP end-point now needs to understand netty internals before he can add an end-point
  3. Lot of boiler plate code, which is not ideal

It would be really unmanageable using the approach highlighted above.

We wanted to use the power of using netty combined with simplicity and ease of use JAX-RS style annotation in building HTTP services. That’s the main motivation to create netty-http library with CDAP as the primary use-case, but designed to be used by any project that needs HTTP services.

Overview of netty-http

netty-http library solves the problems mentioned above by using JAX-RS annotations to build a HTTP path routing layer on top of netty. In addition, the library implements a guava service to manage the HTTP service. netty-http allows users of the library to just focus on writing the business logic in HTTP handlers without having to worry about the complexities of path routing or learning netty pipeline internals to build the HTTP service.

Writing HTTP services using netty-http

HTTP service can be built in three simple steps using the library.

  1. Implement the handler method for the intended functionality
  2. Annotate the handler using JAX-RS with Path and HTTP Method
  3. Setup the HTTP service using the builder

The following code builds a HTTP service that responds to ping requests.

Support for streaming use-cases

The library also supports streaming use-cases where the end-point needs to handle chunks of data. In order to support this use-case an abstract class called BodyConsumer is implemented that has following methods

  1. chunk – to handle chunks as it is received
  2. finished – method that is called after all the chunks are received
  3. handleError – method that is called in the event of failure

The following example illustrates how a large file upload is handled using netty-http

How it works

The basic idea behind the request routing is very simple. On service startup – all the handler classes are inspected and a mapping of all the HTTP path routes to corresponding handler method is maintained.

Any incoming request is handled by the RequestRouter upstream handler, that looks up the internal mapping and invokes the appropriate method using reflection.

image00
 

If no handler is matched then a 404 is returned. If a handler is matched but the HTTP method doesn’t match then a 405 is returned.

CDAP powered by netty-http

We use netty-http in all of the HTTP end-points that we expose in CDAP. Last time I checked, we have about 350 HTTP end-points for various complex interactions.

$ find . -name '*.java'  | xargs grep "@Path("   | grep -v test  | wc -l
     350

Using netty-http has reduced a lot of code complexity at Cask and has made it extremely easy to build HTTP services.

You can leverage with power of netty and simplicity of JAX-RS in your own project by using netty-http.

If you are interested in working on such exciting open-source projects join us! We are developers solving challenging problems to enable rapid development of applications on Hadoop and are looking to hire talented software engineers!  

<< Return to Cask Blog