This post is the first of a serie on KillrChat, a scalable chat application I developed as a hands-on exercise for Cassandra data modeling.
I What is KillrChat ?
KillrChat has been developed with horizontal scalability in mind. It means that today, with a dozen of users, the chat can run on a small box or even a VM but if the users count increases in the future, the design can scale by adding new hardware and without breaking the code to re-design from scratch.
II Why KillrChat ?
After 4 months giving talks and hands-on sessions on Cassandra, I just realised that most of hands-on exercises are mere pieces of real word examples or some HelloWord/TODO List application. Those examples are not really consistent and can not be re-used by the attendees. Thus the idea to provide a real and usable application, to make people design the data model in Cassandra and code the data access part.
This project was also an opportunity for me to strengthen some of my front-end development skills and learn AngularJS in depth.
In fact, as a technical evangelist, most of my time is spent on public talks. Such a development project keeps me in touch with the development, which is always a good thing.
III The technology stack
For the database, the choice was obviously Apache Cassandra™. To take care of the repository layer, instead of using the raw Datastax Java Driver, I used Achilles as an object mapper to make my life easier. Furthermore, Achilles provides some nice support for TDD.
For the front-end, I choose AngularJS for several reasons:
- it is easy to learn
- it is very extensible thanks to the directive system
- the framework focuses on developer productivity, with a declarative (instead of imperative) programming style
- technical resources and tutorial are quite abundant on the web
- last but not least, there is a nice integration module for Twitter Bootstrap. Since my web design skills are so lame, I’m more than happy having Twitter Bootstrap at hand. At worst, my front-end UI would look standard and common, but never really ugly (how can you create an ugly interface with Bootstrap anyway …)
As already mentioned, I pulled an integration of AngularJS with Twitter Bootstrap, called UI-Bootstrap.
For the glue between the front-end interface and the database, I opted for a classical Spring stack.
- Spring Boot with an embedded Jetty server for the application skeleton
- Spring Boot Security to take care of the security part (at least account creation + login/logout)
- Spring Boot Web for the HTTP REST communication with the front-end
- Spring Boot Messaging as the broker for the Web Socket server-side
Some interesting notes about the Web Socket feature. I spent many time playing with Atmosphere but there is so much boilerplate code to make it integrate with Spring that I just gave up. Instead, Spring Boot proposed a very nicely packaged Web Socket architecture with SockJS on the client-side and Spring Messaging at the back-end.
Indeed, a Web Socket can be seen as an abstraction of a publish/subscribe broker. Many clients can subscribe to the same chat room to receive updates on new chat messages. The Spring team did a good job of extracting the broker part from their very mature Spring Integration project to create a more lightweight Spring Messaging module.
So in a nutshell, from top to bottom, below is the technology stack:
- UI Bootstrap
- Spring Boot Jetty
- Spring Boot Web
- Spring Boot Security
- Spring Boot WebSocket
IV The architecture
A Local mode
On a single node, the architecture would resemble this:
In this mode, on the back-end side, everything can be embedded in the Tomcat/Jetty server, including an in-memory broker for the Web Socket and an embedded Cassandra.
B Scale-out mode
On a fulll-fledged production deployment, the architecture would be:
To cope with the high traffic, the number of instances of Tomcat/Jetty servers can be increased. Since the back-end application is stateless (there will be still some session-stickiness handled by the load balancer), we can throw in new boxes to support the load.
On the broker side (necessary for the Web Socket publish/subscribe pattern), we need to use a dedicated infrastructure. A solution like RabbitMQ/ZeroMQ can be a good fit. If you need extreme scalability/fast response time, Apache Kafka could be also a good choice. All you’ll need to implement is a connector between this broker and the Spring Messaging abstraction on each back-end server
For the database, a full Cassandra cluster with horizontal scaling-out is sufficient to cope with any increase in term of traffic.
V The application
A Where to get it ?
KillrChat is an open-source application. You can get it there.
Please ensure that you have the following dependencies installed before-hand:
You’ll need to install Git and clone the GitHub repository locally to run KillrChat
> git clone https://github.com/doanduyhai/killrchat.git
Running in development mode
Go to the Git repository you just cloned before.
To run KillrChat in development mode
killrchat> mvn clean test
killrchat> mvn spring-boot:run -Pdev
When running the application in dev mode, Achilles will start an embedded Cassandra server and create the following data folders:
You can change those default values in the src/main/resources/config/application.yml file.
Then connect to the chat by opening your browser at http://localhost:8080/killrchat/index.html.
Running in production mode
You’ll need to have a Cassandra 2.1 running somewhere so that KillrChat can connect to. If you’re deploying on multiple back-end servers, do not forget to configure properly the broker and not re-used the in-memory version.
To run KillrChat in production mode:
killrchat> mvn spring-boot:run -Pprod
When running the application in prod mode, Achilles will connect to an existing Cassandra server using the server host and port in the the src/main/resources/config/application.yml file. By default Achilles will execute the src/main/resources/cassandra/schema_creation.cql script to provision the killrchat keyspace and appropriate tables.
Then connect to the chat by opening your browser at http://your_back-end_ip:8080/killrchat/index.html.
To be continued …