Email iconarrow-down-circleGroup 8Path 3arrow-rightGroup 4Combined Shapearrow-rightGroup 4Combined ShapeUntitled 2Untitled 2Path 3ozFill 166crosscupcake-icondribbble iconGroupPage 1GitHamburgerPage 1Page 1LinkedInOval 1Page 1Email iconphone iconPodcast ctaPodcast ctaPodcastpushpinblog icon copy 2 + Bitmap Copy 2Fill 1medal copy 3Group 7twitter icontwitter iconPage 1

Background

We were recently asked to build a web application which would require us to deal with data in near real-time. During a number of discovery workshops with the client we ascertained that we needed to update data on up to 100 individual users’ browsers (some of which were in Europe and others in Asia) with a maximum transaction time of one second from one browser to the other. We’ve built plenty of large scale JavaScript applications before but this was the first time we’ve had to deal with real-time data and we needed proof that it was possible to meet the constraints of the system and that we could build a satisfactory solution with technology we are comfortable with.

To achieve this we needed to understand how other applications are doing it, decide on an approach that would work with the clients requirements and our skill set and build something measurable which would prove that we could deliver a solution that would be capable of meeting the clients’ needs within their budget.

And the challenge? We had to do all of this within a single proof of concept sprint (2 developers and 1 week).

Understanding real-time

Before we began building the proof of concept, we needed to gain a greater understanding of the technologies that were available to us. We embarked on a mission to research how other applications are dealing with real-time data and discussed as a team once each of us had a reasonable understanding.

Our research pointed towards WebSockets as the best way to deal with real-time data. WebSockets is web protocol which establishes a persistent connection between the client and the server, allowing both parties to send messages at any time. WebSockets is used by many large applications to provide a real-time solution. One notable case study of an implementation is by Trello, which is definitely worth a read if you’re interested in real-time applications. Incidentally, Trello is a web application we rely on for our day-to-day workflow.

In the course of our research we evaluated a number of “out of the box” solutions such as SocketStream, Derby, Meteor, and a fully hosted service called firebase. Whilst all of these solutions might do part of what we wanted and were very easy to set up, none were quoted as “production ready”. The upshot is they might have been useful for us in our proof of concept as they would allow us to get something up and running very quickly but when it came to building the actual application these solutions would not put us on a good footing, so we ended up discounting them. The real decision was based on what would work for us not only for the proof of concept but for the more challenging software itself.

Real-time for UVD

Because the majority of our applications are built in PHP (Symfony 2), the natural approach was to try and look for a PHP implementation of WebSockets. While there are some PHP implementations for WebSockets, none of them really met our requirements. This lead us to look into NodeJS and SocketIO. On paper, the combination of these technologies met all of our requirements, had browser support all the way down to at least IE8 (which we needed) and gracefully degrades for those browsers not able to support the WebSocket protocol. Importantly, because of our wealth of JavaScript experience we were confident that we could use Node to build a piece of software using the methodologies that serve us so well when building robust web applications (eg: Test Driven Development and Behaviour Driven Development).

Building the proof of concept

Once the decision on technology was made, it was time to start building. As this was a proof of concept, we decided to forego our usually strict BDD and TDD development methodology and to some extent hack the concept together (as mentioned, we were confident we could support TDD and BDD for a production ready NodeJS application but didn’t want to get bogged down setting up continuous integration and a test suite at this stage). With this approach were able get a good understanding around implementation without spending too long designing the full solution. After Eddy did some research on suitable JavaScript frameworks for real-time applications we settled on using AngularJS for the frontend, whilst the backend was built in NodeJS. After coming together to design the data structures and a basic schema design we were off and able to prototype very rapidly.

Initially we wanted to have the data stored in a MongoDB database because MongoDB is often seen as the natural partner for NodeJS and for real-time applications the schemaless data structure and speed of data insertion appealed to us. After digging a bit deeper though, it became evident that it might not satisfy all of our requirements for data storage because whilst it has transactional support at a document level, it is not ACID compliant. Our application would require us to insert multiple documents into the database in one transaction and we needed to be confident that in the event of an error during insertion or updates to the database, there would be a consistent result. You can see this problem occur on Trello when you use a feature like ‘Archive all Cards in This List’ and it fails half way through – the result can be that some cards are archived and some remain on the board. This is acceptable for Trello but definitely not for our application.

Since MongoDB does not have transactional support we needed to look into some alternatives and after some further research of different NOSQL and SQL databases, we decided to see how well MySQL would fare. We know MySQL very well, it has transactional support and can perform well for smaller data sets.

Measurement

There were several aspects of the implementation that we wanted to isolate and test. These were network latency, database speed, and browser speed. To test all of these aspects we configured the proof of concept to run on our local machines and inserted code to spit out a timestamp at a few key points in the application. This allowed us to track where time was being spent.

To test network latency, we set up 2 servers in different locations. We already make extensive use of Amazon Web Services (AWS), so we were able to quickly set up one server in EU-West-1, which is based in Ireland, and another server in Sydney, Australia. We chose Sydney as it’s the furthest data centre away from us here in London.

The different database types were tested by switching out the persistence of data in the backend from MongoDB to mySQL. Once this was working satisfactorily on our local machines, we put these applications on our 2 servers, and re-ran the test.

Cross browser support is important, so we compiled a list of browsers we wanted to test based on the way they dealt with WebSockets. Chrome was an obvious choice, has full WebSocket support, and is used by most (if not all) of us here. Firefox 21 is another good browser and has full WebSocket support, so we wanted to see how it compared to Chrome. Delving into IE is always a bit of a minefield and the one we were slightly apprehensive about. IE provided a good opportunity to test how much of an effect SocketIO’s fallback systems would have on performance. IE 10 is the first IE browser to have WebSocket support, so we added it to the list in case Microsoft had added any ‘eccentricities’ to it’s implementation but the lowest version of IE we were required to support was IE8 and as it doesn’t have WebSocket support, this was where SocketIO’s built in fallbacks came into play. The first relies on Flash and if Flash is not installed, it downgrades to long polling. We therefore needed to test with and without Flash.

All of these different variations were tested and averaged over 10 and 60 iterations to give us our results.

Our Findings

We knew that we had to be able to provide near real-time data (end-to-end in under 1 second) but as our proof of concept wasn’t a full implementation we assumed that there would be some factors in the finished product which would slow the application down so we decided to err on the side of caution when analysing our results. Any completed event in less than ½ second would be good (marked green above), anything between ½ a second and a second would be satisfactory (marked amber), but more attention would be required and anything over a second is a failure (marked red).

As you can see in the table above, we were mostly green, with all red and amber times being on the servers with the greatest distance to travel. Another interesting point to note is that the difference in times between MySQL and MongoDB were generally insignificant. We were expecting MongoDB times to be hugely different, but these variances were not significant enough for us to rule out MySQL as a possibility.

Conclusion

Our first foray into real-time applications was an interesting learning experience for us and after a lot of research, some well thought out planning and a quick, iterative approach to implementation, not only were we able to get the proof of concept complete and tested within 70 hours but the results proved that given our technology choices, we had utmost confidence in our ability to build an application that satisfied the client’s requirements without an unsatisfactory level of investment or risk.

Share: