📜 ⬆️ ⬇️

Who uses Node.js: Trello (Part 1)

Quite often I meet questions like: “And who in general from large / well-known / prominent IT companies uses Node.js in production?”. January 19, 2012 in the blog of the company Fog Creek, founded by the notorious Joel Spolsky ( Joel Spolsky ), was published an article "The Trello Tech Stack" . It is strange that at Habré it somehow ignored. Therefore, in order to correct this shortcoming, and at the same time set an example of using Node.js in a large project, I did a translation of this article.

The article itself is quite voluminous, therefore it is divided into two parts:

Part 1

Part 2


')

The trello tech stack


Trello’s development began with an HTML layout that Justin and Bobby , the designers of the Trello team, collected in a week. I was struck by how cool he looked and felt. After Daniel and I joined the project to develop a prototype and working version of Trello, the real challenge was to preserve the delightful impressions of the original layout during the creation of the server and the client.

image
The original layout of the Trello.

The layout led us to a one-page web application that creates a client-side user interface and accepts data updates via a communication channel with the north. This was significantly different from any work we previously did at Fog Creek. Thus, from a technical point of view, the development of Trello was an adventure.

At first, we were surprised at how interesting and diverse the [application] structure could be, before the management of the [project] became disturbed, our problems were solved at the primary meeting with Joel when he said: “Use solutions that will work fine for two years ".

So we did. We have consistently selected promising (and often challenging) technologies that will provide a terrific experience compared to more mature alternatives. We have been doing this for about a year, and we like it.

CoffeeScript


Trello development started in pure JavaScript on both the client and the server side, and followed this path until May when we copied a couple of files to CoffeeScript as an experiment to see if we would like it. We really liked it, and very soon we rewrote the rest of the code and continued to develop completely in CoffeeScript.

CoffeeScript is a language that compiles into easy-to-read JavaScript. It already existed when we started developing Trello, but I was worried about the added complexity caused by debugging the compiled code, instead of directly debugging the source files. When we tried it, however, the conversion turned out to be so high-quality that when mapping the final code to the source files during debugging in Chrome, a little mental effort was required. And the gains from short code and ease of reading when using CoffeeScript were obvious and convincing.

JavaScript is a cool language. Well-written CoffeeScript smooths and shortens JavaScript, along with it retains the same semantics, and does not introduce a significant problem in debugging.

Customer



Trello servers, in essence, do not work with HTML. In fact, they do not execute a lot of client code. The Trello page is a lightweight (2KiB) shell (thin shell) that downloads the client application from the server as one minimized and compressed JS file (including third-party libraries and our compiled CoffeeScript files and Mustache templates) and one CSS file (compiled from our LESS files and including inline images. All it takes is less than 250KiB, and we distribute it from Amazon's CloudFront CDN. This way we get low latency downloads for most users. In the case of a fairly high-speed connection (high-bandwidth), we get the download and launch of the application in a browser window in about half a second. We also have the benefit of caching, and so on subsequent visits to Trello, that part of the [download] is skipped.

In parallel, we removed the download of AJAX data from the start page and try to establish a WebSocket connection to the server.

Backbone.js


When a response comes in with data, Backbone.js takes effect. The idea behind Backbone is to display each model received from the server (Model) using a view (View), and Backbone provides easy ways to:

Gracefully! Using this approach, we get a normal, understandable and supported client application. We build a client-side model cache in a special way to handle updates and simplify the reuse of the model on the client side.

History.pushState


Now that we have the entire client application loaded into the browser window, we don’t want to spend time navigating between pages. We use the HTML 5 History.pushState interface method to move between pages. In this way, we provide correct and consistent links in the location bar [browser element], and when we go, we simply load the data and transfer them to the appropriate controller based on Backbone.

Mustache


We use Mustache - a template language with minimal use of logical constructions - to display our models in HTML. While “using the full power of [substitute_s_to_your_name] templates” sounds good, in practice it turns out that this requires serious discipline from developers to maintain clear code. We were very happy with Mustache's “brevity is the sister of talent” approach, which allows us to reuse the template code without mixing it with the logic of the client and making confusion.

Pushing and polling


Real-time updates (realtime) is not a new thing, but this is an important part when creating a collaboration tool, so we spent some time on this part of Trello.

Socket.io and WebSockets


For those browsers that support this, we used WebSocket connections to push the server for changes made by other people to browsers that listen to the appropriate channels. We use modified (*) Socket.io client and server libraries, which allow us to keep many thousands of WebSocket connections open on each of our servers with minimal CPU and memory usage. Thus, when some action takes place on the board [the Trello element] that you are watching, this action is passed to the process on our server and distributed to the browser with a minimum delay, usually much less than a second.

(*) Currently, the Socket.io server has some problems with scaling to more than 10K simultaneous connections with clients when using multiple processes and Redis storage. And the client has some problems that can lead to opening multiple connections to the same server or to the fact that the client cannot determine that its connection is serviced. There are some problems with making our changes (hacks!) Back into the project - in many cases they only work with WebSockets (the only Socket.io transport we use). We are working on changes that are suitable for general use, to make back into the project.

AJAX requests


They are not intricate, but they work.

image
The initial outline of the architecture.

When the browser does not support WebSockets (hi, IE), we simply make tiny AJAX change requests every couple of seconds while the user is active, and reduce the interval to ten seconds when the user goes into an inactive state (idle). Since the settings of our server allow us to handle HTTPS requests with minimal overhead and keep TCP connections open, we are able to share good experience in using simple requests when necessary.

We tried Comet through low-level transports for Socket.io, and they were all unstable at the time, anyway. In addition, it seems risky to use Comet and WebSockets as the basis for the main feature. We wanted to be able to return to the most simple and well-established technologies if we stumble upon a problem.

We stumbled upon a problem immediately after launch. Our implementation of the WebSocket server began to behave strangely under sudden and massive loads caused by the TechCranch effect, and we were pleased to be able to return to simple requests and adjust the server's performance by adjusting the request intervals during activity and inactivity. This allowed us to smoothly reduce performance when we increased the number of users from 300 to 50,000 over the course of a week. Now we are back to using WebSockets, but we have a working short query system that still seems like a very reasonable reserve.

To be continued...

Source: https://habr.com/ru/post/160305/


All Articles