Netty Hello World
When you read an article about async programming in java you will definitely find at least mentions of Netty. I’ve heard about this library, I know that many high-performance frameworks based on Netty (Akka, Vert.x, the full list is here), but I’ve never tried it. So it’s time to write a hello world application using Netty and scala.
What is Netty
Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients.
Simply put, Netty is going to be useful if you want to write a server that handles all requests in one thread (technically not one) instead of using a separate thread for each client request. What’s wrong with a thread per request approach? - when we get a high load, we need to have a lot of threads to serve all clients, but having many threads causes high memory consumption and many thread context switches (the second reason is more important due to the fact that it is an expensive operation). This approach is very popular, for example, in javascript world. Node.js http server works exactly in this way.
Netty operates with Channels which are abstractions over a socket. As you may see, data can be read from or written to them - all these operations will be non-blocking. In addition, you can combine channels in groups and execute the same operations as for individual channels. If you’re creating server application you need some of the implementations of ServerSocketChannel
. To start working with a server channel, we have to introduce another important thing - thread pools which all the magic will be run on. There are two thread pools which should be passed to the server channel: boss and workers.
The boss one is going to accept incoming connections while the workers process these accepted connections.
What are we going to create
As a demo application, I’m going to code simple app that will be capturing image from webcam and transfer it over websocket to the client side, then javascript will draw it on the canvas - it’s cross-browser and cross-platform solution, you can watch a video even on a mobile device (without audio though).
To capture images from the camera, we’ll use webcam-capture. It’s written in pure java and has very simple api.
Server Side
All the code split into two parts: server side and client side. Due to the fact that I’m learning scala, the server side will be written in scala in java-style (I’m trying to adopt canonical, functional style, but this is tough to do very fast)
As you see, we don’t have many lines of code (thanks, scala!). Let’s go through the all key parts of this code.
There are two methods: the first one connects to default camera and starts capturing images (the details of this process won’t be covered in this article), the second one starts a web server.
To define a server, there is a special class ServerBootstrap
which is a ServerChannel
but with a simplified interface for server creation. It provides builder-style approach for its configuration. Here are main configuration steps:
group
- takes two event loops, the firs one is for accepting incoming connections, the second one is for data processingchannel
- takes a type of the channel that will be createdchildHandler
- takes aChannelHandler
that will initialize a channel. In our case, it is aChannelInitializer
. Its implementation is described below
The last step is bind
, that binds our channel to given port and returns a ChannelFuture
. That ChannelFuture
is used for correct closing of the server channel.
Now let’s go back to ChannelInitializer
. The most interesting part of it is pipeline. Pipeline passes all the date through a chain of ChannelHandler
s. In our case, we have HttpServerCodec
which is a http protocol implementation, WebSocketServerProtocolHandler
easily implements WebSockets (it requires HttpObjectAggregator
) and the last one WebSocketFrameHandler
which is our handler that does simple thing - it add newly connected client to the group of channels. This group is used in parallel thread that captures image and puts the binary into the group. Very simple!
Client side
As per our requirements, the client application should connect to a websocket and render an image once it comes to the client side. Here is all that we need:
This is pure javascipt. We even don’t need jQuery. The first part is standard WebSocket initialization - nothing to comment on it. There are two functions which should be described. arrayBufferToBase64
takes ArrayBuffer (WebSocket in socket.binaryType = "arraybuffer"
mode uses this type of object to pass binaries) and converts to Base64 string. I haven’t written this function, I’ve stolen it from here. And the last key function here is draw
- when we have Base64 binaries of an image we can draw it on a canvas and this is a typical code to do so.
Demo