{"id":1698,"date":"2015-01-30T22:14:05","date_gmt":"2015-01-30T22:14:05","guid":{"rendered":"https:\/\/doanduyhai.wordpress.com\/?p=1698"},"modified":"2018-07-28T07:36:20","modified_gmt":"2018-07-28T07:36:20","slug":"killrchat-a-scalable-chat-with-cassandra-angularjs-spring-boot","status":"publish","type":"post","link":"https:\/\/www.doanduyhai.com\/blog\/?p=1698","title":{"rendered":"KillrChat, a scalable chat with Cassandra, AngularJS &#038; Spring Boot"},"content":{"rendered":"<p>This post is the first of a serie on <strong>KillrChat<\/strong>, a scalable chat application I developed as a hands-on exercise for <strong>Cassandra<\/strong> data modeling.<\/p>\n<p><\/p>\n<h1>I What is KillrChat ?<\/h1>\n<p><strong>KillrChat<\/strong> 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.<\/p>\n<p><!--more--><\/p>\n<p><\/p>\n<h1>II Why KillrChat ?<\/h1>\n<p> After 4 months giving talks and hands-on sessions on <strong>Cassandra<\/strong>, 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 <strong>Cassandra<\/strong> and code the data access part. <\/p>\n<p> This project was also an opportunity for me to strengthen some of my front-end development skills and learn <strong>AngularJS<\/strong> in depth.<\/p>\n<p> 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.<br \/>\n<\/p>\n<h1>III The technology stack<\/h1>\n<p>For the database, the choice was obviously <strong>Apache Cassandra\u2122<\/strong>. To take care of the repository layer, instead of using the raw <strong>Datastax Java Driver<\/strong>, I used <strong>Achilles<\/strong> as an object mapper to make my life easier. Furthermore, <strong>Achilles<\/strong> provides some nice support for <em>TDD<\/em>.<\/p>\n<p>For the front-end, I choose <strong>AngularJS<\/strong> for several reasons:<\/p>\n<ul>\n<li>it is easy to learn<\/li>\n<li>it is very extensible thanks to the <strong>directive<\/strong> system<\/li>\n<li>the framework focuses on developer productivity, with a declarative (instead of imperative) programming style<\/li>\n<li>technical resources and tutorial are quite abundant on the web<\/li>\n<li>last but not least, there is a nice integration module for <strong>Twitter Bootstrap<\/strong>. Since my web design skills are so lame, I&#8217;m more than happy having <strong>Twitter Bootstrap<\/strong> 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 &#8230;)<\/li>\n<\/ul>\n<p>As already mentioned, I pulled an integration of <strong>AngularJS<\/strong> with <strong>Twitter Bootstrap<\/strong>, called <strong>UI-Bootstrap<\/strong>.<\/p>\n<p>For the glue between the front-end interface and the database, I opted for a classical <strong>Spring<\/strong> stack.<\/p>\n<ul>\n<li><strong>Spring Boot<\/strong> with an embedded <strong>Jetty<\/strong> server for the application skeleton<\/li>\n<li><strong>Spring Boot Security<\/strong> to take care of the security part (at least account creation + login\/logout)<\/li>\n<li><strong>Spring Boot Web<\/strong> for the HTTP REST communication with the front-end<\/li>\n<li><strong>Spring Boot Messaging<\/strong> as the broker for the Web Socket server-side<\/li>\n<\/ul>\n<p>Some interesting notes about the <em>Web Socket<\/em> feature. I spent many time playing with <strong>Atmosphere<\/strong> but there is so much boilerplate code to make it integrate with <strong>Spring<\/strong> that I just gave up. Instead, <strong>Spring Boot<\/strong> proposed a very nicely packaged <em>Web Socket<\/em> architecture with <strong>SockJS<\/strong> on the client-side and <strong>Spring Messaging<\/strong> at the back-end.<\/p>\n<p> Indeed, a <em>Web Socket<\/em> 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 <strong>Spring<\/strong> team did a good job of extracting the broker part from their very mature <strong>Spring Integration<\/strong> project to create a more lightweight <strong>Spring Messaging<\/strong> module.<\/p>\n<p>So in a nutshell, from top to bottom, below is the technology stack:<\/p>\n<ul>\n<li><strong><a href=\"https:\/\/angularjs.org\/\" title=\"AngularJS\" target=\"_blank\">AngularJS<\/a><\/strong><\/li>\n<li><a href=\"http:\/\/angular-ui.github.io\/bootstrap\/\" title=\"UI Bootstrap\" target=\"_blank\"><strong>UI Bootstrap<\/strong><\/a><\/li>\n<li><strong><a href=\"https:\/\/github.com\/sockjs\" title=\"SockJS\" target=\"_blank\">SockJS<\/a><\/strong><\/li>\n<li><strong><a href=\"https:\/\/github.com\/spring-projects\/spring-boot\/tree\/master\/spring-boot-samples\/spring-boot-sample-jetty\" title=\"Spring Boot Jetty\" target=\"_blank\">Spring Boot Jetty<\/a><\/strong><\/li>\n<li><strong><a href=\".com\/spring-projects\/spring-boot\/tree\/master\/spring-boot-samples\/spring-boot-sample-web-ui\" title=\"Spring Boot Web\" target=\"_blank\">Spring Boot Web<\/a><\/strong><\/li>\n<li><strong><a href=\"https:\/\/github.com\/spring-projects\/spring-boot\/tree\/master\/spring-boot-samples\/spring-boot-sample-secure\" title=\"Spring Boot Security\" target=\"_blank\">Spring Boot Security<\/a><\/strong><\/li>\n<li><strong><a href=\"https:\/\/github.com\/spring-projects\/spring-boot\/tree\/master\/spring-boot-samples\/spring-boot-sample-websocket-jetty\" title=\"Spring Boot WebSocket\" target=\"_blank\">Spring Boot WebSocket<\/a><\/strong><\/li>\n<li><strong><a href=\"http:\/\/www.achilles.io\" title=\"Achilles\" target=\"_blank\">Achilles<\/a><\/strong><\/li>\n<li><strong><a href=\"http:\/\/cassandra.apache.org\/\" title=\"Cassandra\" target=\"_blank\">Cassandra<\/a><\/strong><\/li>\n<\/ul>\n<h1>IV The architecture<\/h1>\n<h2>A Local mode<\/h2>\n<p>On a single node, the architecture would resemble this:<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/single_node_architecture.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/single_node_architecture.png\" alt=\"Single Node Architecture\" width=\"840\" height=\"357\" class=\"aligncenter size-full wp-image-1700\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/single_node_architecture.png 2132w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/single_node_architecture-300x127.png 300w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/single_node_architecture-1024x435.png 1024w\" sizes=\"(max-width: 840px) 100vw, 840px\" \/><\/a><\/p>\n<p>In this mode, on the back-end side, everything can be embedded in the Tomcat\/Jetty server, including an in-memory broker for the <em>Web Socket<\/em> and an embedded <strong>Cassandra<\/strong>.<\/p>\n<h2>B Scale-out mode<\/h2>\n<p>On a fulll-fledged production deployment, the architecture would be:<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/Production_Architecture.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/Production_Architecture.png\" alt=\"Production Architecture\" width=\"1814\" height=\"906\" class=\"aligncenter size-full wp-image-1746\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/Production_Architecture.png 1814w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/Production_Architecture-300x150.png 300w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/Production_Architecture-1024x511.png 1024w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2015\/01\/Production_Architecture-1170x584.png 1170w\" sizes=\"(max-width: 1814px) 100vw, 1814px\" \/><\/a><\/p>\n<p> To cope with the high traffic, the number of instances of Tomcat\/Jetty servers can be increased. Since the back-end application is stateless (<em>there will be still some session-stickiness handled by the load balancer<\/em>), we can throw in new boxes to support the load.<\/p>\n<p> On the broker side (necessary for the <em>Web Socket<\/em> publish\/subscribe pattern), we need to use a dedicated infrastructure. A solution like <strong>RabbitMQ<\/strong>\/<strong>ZeroMQ<\/strong> can be a good fit. If you need extreme scalability\/fast response time, <strong>Apache Kafka<\/strong> could be also a good choice. All you&#8217;ll need to implement is a connector between this broker and the <strong>Spring Messaging<\/strong> abstraction on each back-end server<\/p>\n<p> For the database, a full Cassandra cluster with horizontal scaling-out is sufficient to cope with any increase in term of traffic.<\/p>\n<h1>V The application<\/h1>\n<h2>A Where to get it ?<\/h2>\n<p><strong>KillrChat<\/strong> is an open-source application. You can get it <strong><a href=\"http:\/\/www.killrchat.com\" title=\"KillrChat\" target=\"_blank\">there<\/a><\/strong>.<\/p>\n<h2>Installation instructions<\/h2>\n<p>Please ensure that you have the following dependencies installed before-hand:<\/p>\n<ul>\n<li><strong><a href=\"http:\/\/www.oracle.com\/technetwork\/java\/javase\/downloads\/jdk7-downloads-1880260.html\" title=\"JDK 7\" target=\"_blank\">JDK 7<\/a><\/strong><\/li>\n<li><strong><a href=\"http:\/\/maven.apache.org\/download.cgi\" title=\"Maven\" target=\"_blank\">Maven 3<\/a><\/strong><\/li>\n<\/ul>\n<p>You&#8217;ll need to install <strong><a href=\"http:\/\/git-scm.com\/\" title=\"Git\" target=\"_blank\">Git<\/a><\/strong> and clone the GitHub repository locally to run <strong>KillrChat<\/strong> <\/p>\n<p> > git clone https:\/\/github.com\/doanduyhai\/killrchat.git<\/p>\n<h2>Running in development mode<\/h2>\n<p>Go to the Git repository you just cloned before.<\/p>\n<p>To run <strong>KillrChat<\/strong> in development mode<\/p>\n<p>killrchat> mvn clean test<br \/>\nkillrchat> mvn spring-boot:run -Pdev<\/p>\n<p>When running the application in dev mode, <strong>Achilles<\/strong> will start an embedded <strong>Cassandra<\/strong> server and create the following data folders:<\/p>\n<ul>\n<li><em>\/tmp\/killrchat_cassandra\/data<\/em><\/li>\n<li><em>\/tmp\/killrchat_cassandra\/commitlog<\/em><\/li>\n<li><em>\/tmp\/killrchat_cassandra\/saved_caches<\/em><\/li>\n<\/ul>\n<p>You can change those default values in the <em>src\/main\/resources\/config\/application.yml<\/em> file.<\/p>\n<p>Then connect to the chat by opening your browser at <strong>http:\/\/localhost:8080\/killrchat\/index.html<\/strong>.<\/p>\n<h2>Running in production mode<\/h2>\n<p>You&#8217;ll need to have a <strong>Cassandra 2.1<\/strong> running somewhere so that <strong>KillrChat<\/strong> can connect to. If you&#8217;re deploying on multiple back-end servers, do not forget to configure properly the broker and not re-used the in-memory version.<\/p>\n<p>To run <strong>KillrChat<\/strong> in production mode:<\/p>\n<p>killrchat> mvn spring-boot:run -Pprod<\/p>\n<p>When running the application in prod mode, <strong>Achilles<\/strong> will connect to an existing <strong>Cassandra<\/strong> server using the server host and port in the the <em>src\/main\/resources\/config\/application.yml<\/em> file. By default <strong>Achilles<\/strong> will execute the <em>src\/main\/resources\/cassandra\/schema_creation.cql<\/em> script to provision the <em>killrchat<\/em> keyspace and appropriate tables.<\/p>\n<p>Then connect to the chat by opening your browser at <strong>http:\/\/your_back-end_ip:8080\/killrchat\/index.html<\/strong>.<\/p>\n<p>To be continued &#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8230;<br \/><a class=\"read-more-button\" href=\"https:\/\/www.doanduyhai.com\/blog\/?p=1698\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[57,55,10],"tags":[],"_links":{"self":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1698"}],"collection":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1698"}],"version-history":[{"count":6,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1698\/revisions"}],"predecessor-version":[{"id":1756,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1698\/revisions\/1756"}],"wp:attachment":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1698"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1698"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1698"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}