Кто использует Node.js: Trello (Часть 2)

в 13:50, , рубрики: html5, Joel Spolsky, node.js, Trello

Это продолжение перевода «The Trello Tech Stack».

Часть 1

  • CoffeeScript
  • Клиент
    * Backbone.js
    * HTML5 History API
    * Mustache
  • Pushing and Polling
    * Socket.io and WebSockets
    * AJAX запросы

Часть 2

  • Сервер
    * node.js
    * HAProxy
    * Redis
    * MongoDB
  • Итак, нравится ли нам это?

Сервер

Node.js

Серверная часть Trello основана на Node.js. Мы знали, что нам будет необходимо мгновенное распространение обновлений, что означает необходимость держать открытыми много соединений [с сервером], таким образом, управляемый событиями (event-driven) не блокирующий (non-blocking) сервер казался хорошим выбором. Node.js также оказался изумительным инструментом для построения прототипа одностраничного приложения. Прототип сервера Trello был на самом деле простой библиотекой функций, которая обрабатывала массивы моделей, расположенные в памяти одного процесса Node.js, и клиентское приложение просто вызывало эти функции с помощью небольшой обертки WebSocket. Для нас это был наискорейший способ начать попытки использовать Trello и убедиться, что разработка движется в правильную сторону. Мы использовали версию-прототип для управления разработкой Trello и остальных внутренних проектов Fog Creek.

К тому моменту, как закончили прототип, у нас был достаточный опыт с Node.js и нас потрясали его возможности и производительность. Таким образом мы продолжали работать и сделали из нашего Trello-Буратино настоящего мальчика, мы дали ему:

  • настоящую БД и схему (node-mongodb-native и Mongoose)
  • основные веб технологии, такие как маршруты (routes) и куки (cookies) (Express и Connect)
  • много процессов на сервере с отсутствием простоев при рестарте [процессов] (Cluster)
  • межпроцессное взаимодействие (publish/subscribe) и обмен (sharing) структурными данными посредством Redis (node_redis)

Node.js великолепен и становится лучше каждый раз, когда активное сообщество выпускает новые и полезные библиотеки. Громадное количество [и вложенность] колбэков, которое вы вынуждены использовать, по началу кажется проблемой, но через пару недель привыкаешь. Мы используем отличную библиотеку async (а так же краткость кода, которую дает CoffeeScript) для сохранения контроля над нашим кодом. Существуют и другие изящные решения, но нам достаточно использования async, чье поведение мы полностью понимаем.

HAProxy

Мы используем HAProxy для балансировки нагрузки между нашими веб-серверами. Он распределяет TCP-соединения между «каруселью» (round robin) серверов, а все остальное оставляет Node.js. Он держит соединения открытыми достаточно долго для возможности применения WebSockets и возможности повторного использования соединения для AJAX запросов.

Redis

Trello использует Redis для недолго живущих данных, которые используются при обмене между серверными процессами, но не сохраняются на диск. Такие объекты как уровень активности сессии или временный ключ OpenID хранятся в Redis, и приложение построено таким образом, чтобы нормально восстановиться после частичной (или полной) потери этих данных. Мы запускаем [Redis] с заданным ключом 'allkeys-lru' и рабочим пространством (working set) по крайней мере раз в пять большим, чем требуется. Таким образом, Redis автоматически удаляет данные, которые давно не были использованы, и восстанавливает их при необходимости.

Одно из наших наиболее интересных использований Redis — это альтернативное использование коротких запросов при рассылке изменений модели обратно в браузеры. Когда объект изменяется на сервере, мы посылаем JSON сообщение во все соответствующие WebSockets для уведомления клиентов и сохраняем это сообщение в списке фиксированной длины для задействованной модели, отмечая, сколько сообщений было добавлено в этот список за все время. Затем, когда клиент, использующий AJAX запросы [а не WebSocket соединение], пингует сервер на предмет обновлений, с момента его последнего запроса, мы можем получить весь серверный ответ до проверки разрешений а в большинстве случаев проверки одного значения Redis. Redis быстр до безумия настолько, что он может обработать тысячи таких проверок за секунду без существенного проседания [производительности] на одном CPU.

Также, Redis служит нашим publish/subscribe сервером, и мы используем его для распространения сообщений об изменении объекта из серверного процесса, сделавшего начальный запрос, во все остальные серверные процессы. Как только у вас появляется настроенный Redis сервер, вы начинаете использовать его для разного рода вещей.

MongoDB

MongoDB удовлетворяет большинству наших запросов к базе данных. Мы хотели, чтобы [сервер] Trello был очень быстр. Одна из крутейших и наиболее озабоченных производительностью команд, которых мы знаем, является располагающаяся по соседству партнерская компания StackExchange. В один из дней, разговаривая за обедом с их ведущим разработчиком Дэвидом (David), я узнал, что хотя они и используют SQL сервер для хранения данных, в действительности они хранят много данных в де-нормированном виде для улучшения производительности и нормализуют их только при необходимости.

image
Trello сегодня.

В MongoDB мы отказались от использования возможностей реляционных БД (то есть произвольных JOIN) в пользу очень быстрой записи, в большинстве случаев более быстрого чтения, и лучшей поддержки де-нормированных данных — мы можем хранить свойства карточки [элемент Trello] в одном документе в БД и все еще иметь возможность запрашивать (и индексировать) вложенные поля документа. Так как мы быстро выросли, то обладание базой данных с производительностью, способной выдержать изрядное количество нарушений в терминах чтения/записи — было очень хорошей вещью. Также, MongoDB очень просто реплицировать, резервировать и восстанавливать (несмотря на фиаско Foursquare).

Еще одна выгода от использования хранилища несвязных документов — это простое использование разных версий кода Trello с одной и той же базой данных, без плясок с бубном вокруг миграций схем БД. У этого много преимуществ при выпуске новой версии Trello — очень редка (если вообще есть) потребность закрывать доступ к приложению, пока мы обновляем или заполняем БД.

Для разработки это тоже просто супер — когда ты используешь hg bisect (или git bisect) для поиска бага в исходниках и тестовую реляционную БД, то для нее нужны дополнительные действия по откату или возврату БД до тестируемой версии (или создания новой БД с нужными полями). Это может серьезно замедлить работу.

Итак, нравится ли нам это?

Нам нравится наш набор технологий. Как заметил Джоел (Joel), мы истекали кровью на всем протяжении разработки, но я не никогда не видел команды, делающей интересное приложение, без кровопролития, связанного с инструментами и компонентами. И не каждый может сказать, что ему действительно нравится то, с чем они пришли к финишу. Как справедливо для большинства приложений, нет компонентов или деталей реализации, необходимых по своей природе. Однако, мы считаем, что это множество отличных open-source проектов ускорило нашу разработку, дало нам солидную и поддерживаемую кодовую базу, с которой мы интенсивно продвигались вперед и сделали Trello более отзывчивым и красивым приложением. Спасибо всем, кто участвовал в этих проектах, это прекрасное время, чтобы быть программистом.

Звучит привлекательно? Попробуй Trello! Это бесплатно.

Все еще не достаточно разговоров? Вот презентация Trello, которую я делал для недавних обсуждений.

Автор: DmitrySokolov

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js