Мы сделали ставку на хорошо поддерживаемые проекты с открытым исходным кодом, такие как Google V8. После обновления с Node.js v6 до v8 эта ставка окупилась. Наши задержки стали более стабильными, а затраты на серверы глобальной инфраструктуры снизились почти на 40%.

В Ably Realtime, распределенной платформе обмена сообщениями между публикациями и подписками, мы используем широкий спектр технологий в нашем стеке реального времени, включая Elixir, Go и Node.js. Хотя Node.js не часто является нашим первым выбором для новых сервисов, наши основные уровни маршрутизации и внешнего интерфейса построены на Node.js, который, несмотря на некоторые хорошо известные недостатки, продолжает очень хорошо нам служить.

Хотя мы постоянно оптимизируем эксплуатационные расходы нашей инфраструктуры, всегда существует компромисс между выделением инженерных ресурсов для сосредоточения на новых доходах (функциях) и снижением затрат (оптимизацией производительности).

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

Речь идет о недавнем обновлении Node.js с v6 до v8. В результате мы увидели два значительных улучшения:

Под нагрузкой производительность менее резкая и более предсказуемая

На приведенном ниже графике вы увидите, что в наших кластерах, содержащих 100 узлов, в самые загруженные периоды мы наблюдали скачки узлов почти до 100% на короткие периоды, несмотря на то, что средняя загрузка ЦП составляла около 50%.

Тем не менее, как только мы завершим обновление до Node.js v8 с сопоставимой нагрузкой на кластер, мы увидим гораздо более предсказуемую производительность без скачков:

Мы можем предположить, какие изменения в базовом V8 ответственны за это, но на самом деле движок V8 JavaScript улучшается по многим направлениям (в частности, компилятор, среда выполнения и сборщик мусора), которые все вместе играют определенную роль.

Затраты на наши деньги значительно улучшились: около 40% реальной экономии

Когда мы провели нагрузочное тестирование в нашей лаборатории на Node.js v6 и Node.js v8, мы увидели, что в указанном регионе производительность увеличилась на 10%. В этом нет ничего удивительного, поскольку улучшения производительности v8 хорошо известны. Однако после того, как мы протестировали v8 в одном из наших изолированных кластеров, обслуживающих реальный производственный трафик, преимущества были гораздо более значительными. В то время как TurboFan и Ignition от Google V8 дали нам возможность увеличить скорость работы на одном и том же базовом оборудовании, упомянутые выше улучшения (которые сделали производительность более предсказуемо плавной на каждом узле) дали нам больше уверенности в отношении истинного запасного мощность, которую мы имели в каждом кластере. Таким образом, мы могли работать с меньшим количеством узлов в большинстве условий.

Как вы можете видеть ниже, в одном из наших наиболее загруженных кластеров под управлением Node.js v8 мы смогли снизить затраты на наши сырые серверы примерно на 40–50%:

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

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

Если бы мы начали с нуля сегодня, мы, вероятно, не использовали бы Node.js так широко, как сейчас. Однако в 2013 году, когда мы запустили Ably Realtime, мы выбрали Node.js в качестве основного уровня маршрутизации, поскольку он предоставил нам технологию, хорошо подходящую для рабочих нагрузок с большим количеством операций ввода-вывода. Это также стимулировало быстрые циклы разработки, и в то время технология показала хорошие результаты по сравнению с другими аналогичными технологиями.

При выборе Node.js мы сделали ставку на то, что со временем он будет становиться быстрее, и это заметно. Это, конечно, неудивительно, учитывая, что в их браузере Chrome используется движок Google V8. С 2015 года в движке V8 каждую неделю менялось в среднем около 20 000 строк кода. Это колоссальные усилия высококвалифицированной команды инженеров.

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

  • GRPC для нашего уровня RPC (снова спонсируется Google)
  • Кассандра для нашего настойчивого слоя
  • Голанг для наших сетевых сервисов и сотрудников.

Некоторые дополнительные примечания:

  • Проницательные читатели могут задаться вопросом, почему нам потребовалось так много времени, чтобы перейти на Node v8, когда его нет больше года. Основная причина в том, что мы предлагаем 100% гарантию безотказной работы (подробнее об этом ниже), поэтому наш подход к зависимостям сторонних разработчиков заключается в том, чтобы там, где это возможно, использовать очень стабильные и хорошо поддерживаемые версии. В случае Node v8 версия LTS была официально выпущена только в конце 2017 года.
  • Некоторое время назад мы поняли, что наиболее вероятная причина, по которой мы не сможем выполнить нашу 100% гарантию безотказной работы, будет связана с ошибкой программного обеспечения, а не сбоем оборудования, инфраструктуры или сети. Наша инфраструктура имеет избыточность на каждом уровне обслуживания, благодаря чему мы можем обеспечить непрерывность работы, несмотря на сбои оборудования и сети. Однако эта инфраструктура не обеспечивает защиты от сбоя программного обеспечения, развернутого в глобальном масштабе. Таким образом, мы локализуем изменения в инфраструктуре для каждого региона, чтобы минимизировать влияние изменений, и делаем то же самое для изменений в нашем программном обеспечении. Однако когда дело доходит до обновляемых зависимостей, мы всегда действуем очень осторожно, так как нецелесообразно глубоко понимать изменения, которые были внесены в предыдущую версию. В результате наш подход к обновлению зависимостей медленнее, требует большего тестирования и развертывается поэтапно от одного экземпляра к одному кластеру, а затем к глобальной службе. Это позволяет нам измерить влияние изменения зависимости с точки зрения задержки, ошибок и использования ресурсов, прежде чем мы решим развернуть его более широко.
  • Rising Stack любезно подвел итоги наиболее значительных изменений в Node v8.
  • Похоже, что Node v10.4 и V8 6.7 значительно улучшат производительность сборки мусора в результате одновременной маркировки. Мы опубликуем обновление, как только изменения коснутся LTS-версии Node.