With our new Cloud service offering at CapTech, I decided I wanted to build something that would give me some experience in the subject. After spending some time thinking of what I should do, I decided to write a client/server chat application and decided up-front that this would be a VERY simple application. This is because my main goals were not to create something elaborate. They were to learn how to work with new technologies and environments. As it turns out, I learned of a tool called Amazon Elastic Beanstalk, which made my initial approach to this app seem primitive. That's exactly the type of thing I was hoping to learn though!

I'll cover my initial solution to developing my application first. When deciding on a technology stack for my chat application, I remembered a C++ application I wrote in college and thought about how I might host that, or a Java equivalent, on AWS (I chose Amazon Web Services mainly because of CapTech's partnership with them, but also because they offer free server instances). That idea quickly faded as I realized it wasn't very cutting edge, or fast to implement, and I had the whole world of open-source software at my disposal. So I went back to the drawing board and found that Node.js would be perfect for this. Since I was going to use Node as my server, it also seemed fitting to use WebSockets for my transport protocol as they're relatively "new", cool, and perform well for this type of communication.

To get my server running, I needed to start a new instance on AWS. I went with an Amazon EC2 Micro instance running Ubuntu server 32-bit. This was extremely simple to setup through the online dashboard and I was done in a few mouse-clicks. There are several free instances you can choose from, and they have different out-of-the-box features including one that comes as a LAMP server, but sometimes I like to do things from scratch. Once the instance is up and running, you can SSH in and begin installing the necessary packages. The packages I had to install include:

  • Apache - to host my interface to the page
  • Node.js - the server that will respond to incoming chat requests
  • ws - a library for Node so that it can use WebSockets on the server
  • Forever - a package that allows Node servers to run indefinitely (note that if you are using Forever programmatically, you should install forever-monitor)

I won't bore you with my setup details; they're only a quick Google search away. I will tell you that I used SSH to access my EC2 instance and used npm to install ws and Forever though. A very important thing to note is that you should consider installing the packages globally! If you don't install them globally, and you try to use one in your Node code, it won't work (just like a missing header declaration). Usually all you need to do is set the "-g" flag on your install command.

My message format below shows how my server would communicate with my client's chat requests. Note that there is no authentication method currently; users simply login with any username they choose (and send it on subsequent calls so the server knows who is sending the message).

var msg = {
 type: messageType,
 text: messageText,
 id: userName,
 date: Date.now()
};

You can find my full code here, but I've included the important server code below.

 // Handle incoming connections and messages
 // WSS is the Server while WS is the incoming client
 wss.on('connection', function(ws) { 
 ws.on('message', function(message) {
 var thisMessage = JSON.parse(message);
 
 switch (thisMessage.type) { 
 case "login":
 wss.handleLogin(thisMessage, ws); 
 break;
 case "message":
 wss.handleMessage(thisMessage, ws); 
 break;
 default:
 wss.handleError(1, ws); 
 break; 
 } 
 }); 
 }); 
 
 // Handles messages from the clients 
 wss.handleMessage = function(message, socket) { 
 wss.broadcast(JSON.stringify(message)); 
 }; 
 
 // Function that broadcasts data to all connected clients
 wss.broadcast = function(data) {
 for (var i in this.clients) {
 this.clients[i].send(data); 
 } 
 }; 

Once I had this all setup, I placed my client-facing interface files in the /var/www via SCP and was ready to go. The last thing to do was to create a Snapshot of my instance so that if and when it failed, I wouldn't have to re-configure the entire server. I could simply launch my snapshot. After that, I had a functioning and easily re-deployable server.

This seemed pretty cool until I heard about Amazon Elastic Beanstalk, or Beanstalk for short. What Beanstalk does is breaks down all these setup steps into a few simple command-line instructions or three steps via their web interface. It is so simple and easy that I can't believe I went through the effort outlined above. You get more out-of-the-box features including load-balancing (which is awesome) and autoscaling. Another feature, which may be my favorite, is that using the command-line interface generates a configuration. This configuration can be started and stopped with one line. No more need to create snapshots and manually configure your server over and over again. The command-line tool also integrates with Git, so you can make code updates and push it to AWS extremely easily with virtually no learning curve.

The setup instructions from Amazon can be found here. These are what I used verbatim to setup my instance. My only hang-up was that I needed to install the ws library for Node to use before running my server code. To do this I ran npm init to help me create a package.json file for my project. This is a sort of configuration file for Node, which, among other things, lists the dependencies of the project. With the creation of this file, I assured the installation of the libraries my code depends on. Just be sure that you npm install the package(s) needed before running npm init.

Potential Issues

Let me start out by saying that most of these hurdles are avoided simply by using Elastic Beanstalk! The only change I made when using Beanstalk was to add my webserver into the Node code. This made the deployment much easier as I only needed one file to run the webserver and chat server.

Nonetheless, this project had a few hurdles where you can hopefully learn from my mistakes. One was a simple firewall setting for my EC2 instance. At first I was not able to reach my Node server from a client. The problem was that I needed to open the ports that Node and the web sockets were using. This is fairly easy, and Amazon has some predefined rule-sets to help you out. AWS Security Groups and Rules

Another issue was keeping the Node server running. I realized that every time I closed my SSH connection, the server would quit. I had already suspected this would be an issue but needed a solution. That solution was Forever. It starts the Node server so that your user is not the process's parent, allowing you to logout of your EC2 instance while leaving the server running. Using it is as easy as the following one line command:

Forever start server.js

In conclusion, it is very easy to get started with cloud development. It's also free for small-scale use! I think what's really cool about this is how simple it is to run a functioning Node server. You really just have to run a few commands or click a few buttons on Amazon's web interface if you're using Beanstalk. Otherwise, with EC2, you can use SCP to copy your code and HTML files to the instance, and then run it via SSH. Don't forget that Beanstalk comes with load-balancing and autoscaling built-in though! For these reasons I have to recommend using Beanstalk, and specifically the Beanstalk CLI tool. It's so simple and quick. EC2 is great, and I might use it if I needed to do something very custom, but the power you get out-of-the-box with Beanstalk is awesome. If nothing else though, working in the cloud is a good way to get some experience with new and exciting technologies.