Pull to refresh

12 подсказок для масштабирования Node.js

Reading time8 min
Views7K
Node.js уже сейчас успешно работает в мировом масштабе, об этом свидетельствую развернутые приложения на нем таких компаний как Netflix, Reddit, Walmart и Ebay. Однако, он имеет свой набор проблем при масштабировании; как с точки зрения масштабирования людей, работающих над единой базой кода, так с точки зрения вертикального и горизонтального масштабирования в облаке. К дополнении моему личному опыту масштабирования Node.js при работе в таких компаниях, как Reddit и Netflix, я поговорил с некоторыми экспертами, работающими в Microsoft Azure, и придумал несколько советов для вас по масштабированию Node.js в вашей компании.

Пишите качественный Node.js


Чем раньше вы начнете использовать линтеры, инструменты для форматирования и проверки типов в вашем коде, тем лучше.

Эти вещи могут быть сложны при введении в середине проекта в связи с потенциально большим количеством рефакторинга, который может потребоваться, это также может загрязнить вашу git-историю, но в конце эти инструменты помогут тебе сделать код читаемым.
Если вы их до сих не используете, немедленно обратите свой взгляд в сторону ESLint и Prettier. ESLint защитит ваш код от плохих патернов, Prettier же поможет автоматически отформатировать ваш код перед pull request`ом.

Более существенное решение — это добавлении инструментов, таких как Flow или TypeScript в вашу кодовую базу. Эти инструменты позволяют поймать более тонкие ошибки, вроде вызова функции с числовым параметром вместо строкового или вызова метода .filter у объектов вместо массива. Несмотря на сложность и необходимость обучения вашей команды, эти инструменты заслуживают ваше внимание: они могут ускорить разработку благодаря Intellisense и предотвращения runtime ошибок благодаря защите типов.

Пишите тесты


Тесты всегда были сложным вопросом для разработчиков. Некоторые основательно верят в test-driven development, пока другие редко вообще пишут тесты. Но есть золотая середина:

  • Определите ключевые модули и напишите для них исчерпывающие unit test`ы. Обратите специальное внимание на “счастливые пути”: краевые случаи и сценарии, в которых могут потенциально возникнуть ошибки. Для других модулей, пишите один или два unit test’а охватывающие “счастливые пути” и, возможно, общие случаи, которые вы смогли обнаружить
  • Минимум UI test. UI постоянно меняется и часто нецелесообразно тратить кучу времени на выполнение тестов для кода, который будет часто меняться.
  • Пишите тесты для обнаружения багов. Всякий раз, когда вы находите и исправляете ошибку в коде, напишите единичный тест, который поймает эту ошибку в будущем.
  • Пишите несколько интеграционных тестов, чтобы убедиться, что все части соответствуют друг другу.
  • Пишите еще меньше end-to-end тестов. Покройте ключевые пути на вашем сайте, для примера, если вы создаете e-commerce сайт, возможно, стоит написать тест для входа на сайт, для добавления в корзину и проверки списка товаров. Эти тесты дорогие для поддержания, поэтому подумайте о том, чтобы сохранить небольшое ядро таких тестов, которые вы сможете смотивировать себя поддерживать.

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

Проектирования без гражданства


Ключ при написании масштабируемого Node.js заключается в том, что ваши сервера не должны хранить состояния для кого-то или чего-то. Это будет препятствовать масштабирования по горизонтали. Переместите состояние в другое приложение и решите проблему в другом месте (например, Redis, Etcd, …). Об этом стоит подумать заранее. Потом это будет очень сложно распутать, если вы не сделали этого ранее. Это также поможет, если вы когда-нибудь решите разложить монолиты на микросервисы.

Cтатика: для development — Node.js, для production — CDN


Как бы я хотел, чтобы компании видели ошибку в этой ошибке. Обслуживание ваших статических активов из вашего веб-приложения (в частности, через что-то вроде webpack-dev-server или Parsel’s dev server) — отличный опыт разработчика поскольку он сокращает цикл введения при написании кода. Однако вы никогда не должны обслуживать вашу статику через Node.js. Она должны поставляться отдельно через CDN, например Azure CDN.

Отдача статики с Node.js излишне медленна, поскольку CDN более разбросаны и, следовательно, физически ближе к конечному пользователю, к тому же CDN серверы высоко оптимизированы для небольших по объему ресурсов. Обслуживание статики с Node также неоправданно дорого, так как время сервера Node.js намного дороже, чем время сервера CDN.

Начни деплоить пораньше, деплой почаще


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

К слову, Visual Studio Code позволяет решить такого рода проблему. Он позволяет одним кликом развернуть ваше приложение прямо на Azure. Это достаточно простой способ, чтобы проверить отсутствие проблем при развертывании в другой среде.

Разверни 2 сервера сразу


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

Не бойтесь очередей


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

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

Если у вас возникла или потенциально скоро возникнет такая проблемы, у вас будут варианты выбора технологий, с которыми вы пойдете дальше. Одной из таких технологий может стать очередь сообщений. Фактическим стандартом на данный момент является Apache Kafka, который позволяет организовать ваши сообщения в топики, а затем приложениям подписать на этот топик. Так, например, вы можете накапливать сообщения в приложении, слушая определенный топик, а потом пакетно записывать данные в свою базу данных, чтобы она не забивалась всё время. К тому же Kafka легко запускается на Azure.

Микросервисы для масштабирования


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

Используйте контейнеры


Ваше приложение может хорошо работать локально, но при попытке деплоя могут возникнуть серьезные проблемы. Дабы избежать этой проблемы вам подойдут такие инструменты, как Docker и Kubernetes. Docker, который вы можете представлять как мини-экземпляр (контейнер) Linux или Windows, в котором вы можете запускать приложении; и Kubernetes в качестве инструмента, который подключает все ваши контейнеры вместе в облаке.

Kubernetes может быть сложным зверем, но зверем который решает сложную проблему. Если вы неопытный DevOps колдун, то у вас могут возникнуть сложности, поэтому я рекомендую начать с Draft. Если вы знакомы с Yeoman для Javascript проектов, то вы можете оценивать Draft, как схожий инструмент, но для Kubernetes проектов: инструмент, который создает каркас для вашего проекта. Оттуда вы можете использовать инструмент Helm для установки дополнительных фрагментов архитектуры, которые вам нужно собирать (например, nginx, больше серверов Node.js, MongoDB, Kafka и т.д.), почти как npm для Kubernetes.

Как только вы разберетесь в экосистеме Kubernetes, для вас впредь деплой в облаке станет детской игрой.

Собирайте метрики


Если вы не знаете, как ответить на вопрос “Как работает мое приложение ?”, тогда у вас проблемы или уже скоро будут. Ведь разного рода показатели с течением времени помогут вам постоянно улучшать состояние вашего приложения. С точки зрения затрат на перспективу, так и с точки зрения удобства пользователя в плане улучшения времени отклика. Вы определенно должны следить за такими показателями, как медленные пути, просмотры страниц, время сеанса и другие ключевые показатели, которые важны для вашего бизнеса.

Есть много способов собирать эти показатели. Такие службы, как New Relic и AppDynamics, предоставят вам неоценимую информацию о том, как улучшить ваше приложение.

Если вы работаете с Azure, Application Insights также хорошо справляется с этой потребностью, к тому же легко подключить другие инструменты, такие как CI/CD.

CI/CD спасет вас от стольки боли


Как много раз вы портили развертывание при FTP и сбивали свой сервер на несколько минут? Со мной было. Вы никогда не должны доверять себе в развертывании производственного кода. То, как это сделать с помощью Visual Studio Code, довольно круто, но оно предназначено в основном для разработки или с целью демонстрации. Когда вы будете готовы к созданию системы уровня production, вы должны использовать непрерывную интеграцию и непрерывное развертывание (частое сокращенные CI/CD — continuous integration and continuous deployment).

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

Непрерывное развертывание занимается тем, что принимает ваш код, который передал CI, запускает необходимые шаги для сборки, контейнеризирует или упаковывает их и отправляет на сервер. Хорошей практикой является иметь несколько уровней для проверки. Возможно, вы сначала перейдете на внутренний сервер dev, чтобы сначала увидеть его в среде с низким уровнем риска. Вы можете проверить его сначала, прежде чем отправлять его в среду QA, где ваши инженеры по QA или, возможно, внешняя служба подтвердят, что все работает так, как ожидалось. Оттуда вы можете перейти в промежуточную среду, в которой ваше приложение по-прежнему остается только внутренним, но работает с использованием производственных данных и настроек, поэтому вы можете проверить его в самой производственной среде, прежде чем отправлять его непосредственно в production. Также вы можете выделить небольшую группу серверов для проверки нового кода: вы и только небольшой процент реального трафика направлять на эти сервера, чтобы убедиться, что ничего не ломается при работе с реальными пользователями. Если он ломается, вы знаете, где искать проблему. Если нет, можно переходить от небольшой группы пользователей ко всем.

Многие поставщики и проекты с открытым исходным кодом обращаются к этим потребностям. Jenkins, Travis и CircleCI — отличные варианты для CI. Azure имеет свой собственный сервис CI/CD под названием Azure Pipelines, и он довольно интуитивно понятен в использовании, и снова он легко подключается к объединенной экосистеме Azure.

Храните секреты


Любое приложение неизбежно имеет какие-то секреты. Это могут быть ключи и секретные строки от учетных данных, баз данных и много чего еще. Было бы очень плохо, если бы они превратились в чужие руки. Однако они необходимы для запуска приложения. Так что же нам делать? Обычно в разработке мы будем использовать такие инструменты, как dotenv, чтобы локально сохранять файл конфигурации и иметь возможность читать его через process.env в Node.js. Это отлично подходит для разработчиков, но ужасно для production.

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

Другим инструментом, заслуживающим вашего внимания, является Key Vault от Azure. Что круто в Key Vault, несмотря на то, что Microsoft не может читать ваши ключи (только у вас есть возможность расшифровать их) Azure будет следить за вашими журналами и следить за любыми сомнительными использованиями ваших ключей, чтобы предупредить вас о любых компрометациях.

Вывод


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

Оригинал статьи: “Eleven Tips to Scale Node.js” (En).

Предлагаю в комментариях поделиться советами, которые вы можете дать по масштабированию Node.js. Будет интересно услышать.
Tags:
Hubs:
+2
Comments5

Articles