Pull to refresh

Нагружаем Node под завязку (2-я из 12 статей о Node.js от команды Mozilla Identity)

Reading time7 min
Views19K
От переводчика: Это вторая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona. Эта статья написана по мотивам выступления Ллойда Хилайеля на конференции Node Philly 2012 в Филадельфии.





Процесс Node.js выполняется на единственном ядре процессора, так что построение масштабируемого сервера на Node требует особой заботы. Благодаря возможности писать нативные расширения и продуманному набору API для управления процессами, есть несколько разных способов заставить Node выполнять код параллельно. Мы рассмотрим их в этой статье.

Кроме того, мы представим модуль compute-cluster — маленькую библиотеку, которая облегчает управление коллекцией процессов для выполнения распределённых вычислений.

Постановка задачи


Для Persona нам было необходимо создать сервер, который справился бы с обработкой множества запросов со смешанными характеристиками. Мы выбрали для этой цели Node.js. Нам надо было обрабатывать два основных типа запросов: «интерактивные», которые не требовали сложных вычислений и должны были выполняться быстро, чтобы интерфейс приложения был отзывчивым, и «пакетные», которые отнимали примерно пол-секунды процессорного времени и могли быть ненадолго отложены без ущерба для удобства пользователя.

В поисках наилучшей архитектуры приложения мы долго и тщательно обдумывали способы обработки этих типов запросов с учётом юзабилити и стоимости масштабирования и в конце концов сформулировали четыре основных требования:

  • Насыщение. Наше решение должно было использовать все доступные ядра процессора.
  • Отзывчивость. Пользовательский интерфейс должен оставаться отзывчивым. Всегда.
  • Отказоустойчивость. Когда нагрузка зашкаливает, мы должны нормально обслужить столько клиентов, сколько сможем, а остальным показать сообщение об ошибке.
  • Простота. Решение должно легко и постепенно интегрироваться в уже работающий сервер.


Вооружившись этими требованиями, мы можем осмысленно сравнивать разные подходы.
Читать дальше →
Total votes 39: ↑38 and ↓1+37
Comments5

Храним сессии на клиенте, чтобы упростить масштабирование приложения (3-я из 12 статей о Node.js от команды Mozilla Identity)

Reading time4 min
Views20K
От переводчика: Это третья статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona. Эта статья посвящена применяемому в Persona способу хранения данных сессии на клиенте.




Статические веб-сайты хорошо масштабируются. Их легко кэшировать, и не нужно постоянно синхронизировать данные на нескольких серверах.

К сожалению, большинство веб-приложений должны хранить информацию о состоянии, чтобы предлагать пользователям персонализированные страницы. Если пользователи могут регистрироваться на сайте, то нам надо хранить сессии. Самый распространенный способ — установить cookie со случайным идентификатором сессии, а детали хранить на сервере.

Масштабирование сайта с хранением состояния


Если необходимо масштабировать такой сайт, есть три варианта:

  1. Реплицировать данные сессии между всеми серверами.
  2. Использовать центральное хранилище, к которому будут обращаться все серверы.
  3. Закрепить за каждым пользователем определённый сервер.

У всех этих подходов есть недостатки:

  1. Репликация ухудшает производительность и увеличивает сложность.
  2. Центральное хранилище ограничивает возможность масштабирования и приводит к дополнительным задержкам.
  3. Привязка пользователей к конкретным серверам приводит к проблемам, когда сервер отключается.

Тем не менее, поразмыслив немного, можно придумать и четвёртый способ: хранить все данные сессии на клиенте.
Читать дальше →
Total votes 22: ↑18 and ↓4+14
Comments14

Приручаем конфигурации веб-приложений с помощью node-convict

Reading time6 min
Views9.4K
От переводчика: Это седьмая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





В этой статье из цикла о Node.js мы рассмотрим модуль node-convict, который помогает управлять конфигурациями приложений Node.js. Он предоставляет прозрачные настройки по умолчанию и встроенную типизацию, чтобы было легче находить и исправлять ошибки.

Постановка задачи


Есть две основные проблемы, которые создают необходимость в конфигурации приложений:

  • Большинство приложений могут работать в нескольких окружениях, имеющих разные параметры конфигурации.
  • Включение учётных данных и другой конфиденциально информации в код приложения может создавать проблемы.

Эти проблемы можно решить, инициализируя некоторые переменные в зависимости от текущего окружения и используя переменные окружения для хранения конфиденциальных данных. Общепринятый в среде Node.js шаблон для реализации этого подхода состоит в создании модуля, который экспортирует конфигурацию:

var conf = {
  // окружение приложения - 
  // "production", "development", или "test
  env: process.env.NODE_ENV || "development",
 
  // IP адрес
  ip: process.env.IP_ADDRESS || "127.0.0.1",
 
  // Порт
  port: process.env.PORT || 0,
 
  // Настройки БД
  database: {
    host: process.env.DB_HOST || "localhost:8091"
  }
};
 
module.exports = conf;

Это работает неплохо, но есть ещё пара проблем:

  • Что если в конфигурации указаны некорректные данные? Мы можем сберечь время и нервы, обнаруживая ошибки как можно раньше.
  • Насколько легко разобраться в конфигурации администраторам, тестировщикам и другим членам большой команды, когда им надо менять настройки или искать дефекты? Более декларативный и лучше документированный формат сделал бы их жизнь легче.

Читать дальше →
Total votes 21: ↑18 and ↓3+15
Comments1

Производительность фронтэнда. Часть 1 — конкатенация, компрессия, кэширование (4-я из 12 статей о Node.js от Mozilla)

Reading time9 min
Views14K
От переводчика: Это четвёртая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona. Эта статья о том, как увеличить скорость загрузки ресурсов сайта и модуле connect-cachify, созданном в Mozilla для этой цели.





В этой статье мы поговорим о производительности фронтэнда и представим инструменты, созданные в Mozilla для того, чтобы сделать сайт Persona настолько быстрым, насколько возможно. Мы опишем работу с connect-cachify — модулем, автоматизирующим некоторые из важнейших аспектов, обеспечивающих производительность фронтэнда.

Но сначала окинем взглядом наиболее распространённые пути улучшения производительности. Если у вас уже есть опыт оптимизации фронтэнда, можете пропустить эти разделы и перейти в конец статьи, где описано, как с помощью connect-cachify автоматически делать то, что вам раньше доводилось делать вручную.
Читать дальше →
Total votes 19: ↑16 and ↓3+13
Comments2

Пишем сервер, который не падает под нагрузкой

Reading time5 min
Views30K
От переводчика: Это пятая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





Как написать приложение Node.js, которое будет продолжать работать даже под невозможной нагрузкой? В этой статье показана методика и библиотека node-toobusy, её воплощающая, суть которой наиболее кратко может быть передана этим фрагментом кода:

var toobusy = require('toobusy');
 
app.use(function(req, res, next) {
  if (toobusy()) res.send(503, "I'm busy right now, sorry.");
  else next();
});

В чём заключается проблема?


Если ваше приложение выполняет важную задачу для людей, стоит потратить немного времени на раздумья над самыми катастрофичными сценариями. Это может быть катастрофа в хорошем смысле — когда ваш сайт попадает в фокус внимания социальных медиа, и вместо десяти тысяч посетителей за сутки к вам вдруг приходит миллион. Подготовившись заранее, вы можете создать сайт, который выдержит внезапный всплеск посещаемости, превышающий обычную нагрузку на порядки. Если же этими приготовлениями пренебречь, сайт ляжет именно тогда, когда вы меньше всего этого хотите, когда он у всех на виду.

Это может быть и злонамеренный всплеск трафика, например от DoS-атаки. Первый шаг к борьбе с такими атаками — написание сервера, который не падает.
Читать дальше →
Total votes 66: ↑56 and ↓10+46
Comments26

Производительность фронтэнда. Часть 2 — кешируем динамический контент с помощью etagify

Reading time5 min
Views5.6K
От переводчика: Это шестая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





Возможно, вам известно, что Connect ставит ETag-и на статический контент, но не динамический. К сожалению, если вы динамически генерируете локализованные версии статических страниц, они не кешируются вообще, если только вы не решите генерировать их все заранее, на стадии сборки проекта. Этого вполне можно избежать.

Эта статья посвящена etagify — модулю middleware для Connect, который генерирует ETag-и на лету на основе MD5-хешей ответов, и хранит эти хеши в памяти. Etagify избавляет от лишней рутины при сборке проекта, предельно прост в использовании и увеличивает производительность больше, чем можно было бы ожидать (в своих тестах мы получили ускорение загрузки страниц на 9%):

myapp = require('express').createServer();
myapp.use(require('etagify')());
...
app.get('/about', function(req, res) {
  res.etagify(); 
  var body = ejs.render(template, options);
  res.send(body);
});

Читать дальше →
Total votes 26: ↑24 and ↓2+22
Comments0

Производительность фронтенда. Часть 3 — оптимизация шрифтов

Reading time7 min
Views12K
От переводчика: Это восьмая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





Мы смогли уменьшить объем шрифтов для Persona на 85%, с 300 до 45 килобайт, используя подмножества шрифтов. Эта статья рассказывает о том, как именно мы это сделали, и какие мы использовали инструменты.

Представляем connect-fonts


Connect-fonts — это middleware для Connect, которое улучшает производительность @font-face, раздавая клиентам подобранные специально для их языка подмножества шрифтов, уменьшая тем самым их размер. Connect-fonts также генерирует специфические для локали и браузера стили @font-face и CORS-заголовки для Firefox и IE9+. Для раздачи подмножеств шрифтов создаются так называемые font packs — поддиректории с подмножествами шрифтов плюс простой конфигурационный файл JSON. Некоторые наборы распространённых open source-шрифтов доступны в готовом виде в пакете npm, впрочем, создавать свои пакеты совсем нетрудно.

Если вы не слишком хорошо ориентируетесь в работе со шрифтами в интернете, мы собрали небольшую коллекцию ссылок по теме @font-face. [От переводчика: а на Хабре очень кстати статья, посвящённая производительности веб-шрифтов]
Читать дальше →
Total votes 26: ↑24 and ↓2+22
Comments2

Локализация приложений Node.js. Часть 1

Reading time4 min
Views13K
От переводчика: Это девятая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





image

Знаете ли вы, что продукты и сервисы Mozilla локализованы для 90 языков? Локализация включает в себя:

  • текст, переведённый на региональные вариации и диалекты языков;
  • рендеринг страниц с учётом написания справа налево;
  • пуленепробиваемый дизайн, способный вместить тексты любой длины;
  • заголовки, метки и текст на кнопках, подобранные для локальных аудиторий.

В этой серии из трёх статей, посвящённых локализации, я расскажу о технических аспектах создания многоязычного приложения Node.js.

Мы будем использовать общепринятые термины «интернационализация» (i18n) и «локализация» (l10n). Интернационализация — это набор технических приёмов, делающих возможной последующую локализацию, то есть собственно перевод и адаптацию для конкретного языка.

Mozilla Persona — веб-сервис на Node.js, локализованный для множества локалей. У нашей команды были весьма специфические запросы, и поэтому мы не стали использовать существующие библиотеки для локализации.
Читать дальше →
Total votes 36: ↑28 and ↓8+20
Comments1

Awsbox — PaaS-инфраструктура для развёртывания приложений Node.js в облаке Amazon

Reading time5 min
Views4.8K
От переводчика: Это двенадцатая, последняя статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





После того как вы написали приложение на Node.js, как развернуть его на сервере? Вместо того, чтобы использовать готовое PaaS-решение, наша команда создала собственную инфраструктуру поверх Amazon EC2. Сейчас мы расскажем подробнее о том, как мы это сделали.

Мы представим вам awsbox — минималистичный слой PaaS-инфраструктуры для Node.js, который сейчас обслуживает пару дюжин некритичных сервисов Mozilla. Awsbox разработан для того, чтобы предоставить простоту и удобство развёртывания, характерные для PaaS, не теряя при этом гибкости кастомизированной инфраструктуры.
Читать дальше →
Total votes 23: ↑20 and ↓3+17
Comments3

Локализация приложений Node.js. Часть 2: инструментарий и процесс

Reading time7 min
Views6.5K
От переводчика: Это деcятая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





В прошлой статье о локализации приложений Node.js мы узнали, как использовать модуль i18n-abide в нашем коде. Наша работа, как программистов, фактически закончилась на том, что мы обернули строки в шаблонах и коде приложения в вызовы gettext(). Но работа по локализации и переводу приложения только начинается.

Инструментарий


Инструментарий локализации команды Mozilla Persona совместим с теми инструментами, которые используются в остальном сообществе Mozilla, и при этом сохраняет преимущества в дружественности и гибкости, присущие Node.

Проекту Mozilla уже почти 15 лет, и наша команда локализаторов и переводчиков одна из самых больших (и клёвых) в мире Open Source. Поэтому у нас широко используются давно привычные, можно даже сказать старинные и причудливые инструменты.
Читать дальше →
Total votes 14: ↑12 and ↓2+10
Comments3

Локализация приложений Node.js. Часть 3: локализация в действии

Reading time7 min
Views6.1K
От переводчика: Это одиннадцатая статья из цикла о Node.js от команды Mozilla Identity, которая занимается проектом Persona.





Использование строк


Итак, сначала мы подключили к нашему приложению модуль i18n-abide и обернули строки в вызовы gettext. Затем наша команда переводчиков перевела эти строки и у нас есть готовый перевод для каждого языка.

Теперь давайте заставим наше приложение Node.js работать с локализованными строками. Переводы в виде po-файлов лежат в файловой системе в таком виде:

locale
  en
    LC_MESSAGES
      messages.po
  de
    LC_MESSAGES
      messages.po
  es
    LC_MESSAGES
      messages.po

Во время выполнения нашего приложения нужно извлекать переведённые строки из этих файлов. Есть два способа сделать это:

  • на стороне сервера с помощью всё той же функции gettext из модуля i18n-abide;
  • на стороне клиента с помощью скрипта gettext.js, который также входит в состав i18n-abide.

Оба этих метода требуют, чтобы строки были в формате JSON. При переводе на стороне сервера они загружаются при старте приложения, а клиент загружает их с помощью HTTP-запросов (или можно включить их в минифицированный файл JavaScript в процессе сборки).

Так как наша система перевода совместима с GNU Gettext, есть ещё и третий путь — модуль node-gettext. Он довольно эффективен при переводе на стороне сервера.

Дальше мы будем рассматривать первый способ, так как это наиболее привычный способ использования i18n-abide.
Читать дальше →
Total votes 12: ↑10 and ↓2+8
Comments2