написать впереди
Эта статья призвана предоставить некоторые основные идеи и решения для распространенных сценариев для студентов, изучающих передний план в проектировании архитектуры серверных проектов nodejs. Разработка сервисов узлов — это, по сути, категория разработки на стороне сервера, однако из-за популярности различных приложений, разработанных с помощью nodejs, и расширения цепочки интерфейсных инструментов на сторону сервера требования к полному стеку Возможности развития фронтенд-студентов также увеличиваются в этой статье. Поскольку разработка на стороне сервера сама по себе является очень большой темой, в этой статье будут объединены несколько простых для понимания примеров для быстрого охвата. В то же время, в конце статьи я возьму в качестве примера свою недавнюю распределенную трансформацию и многоузловое развертывание интерфейсных унифицированных сервисов упаковки в своей компании, чтобы описать некоторые практики.
распределенный, сгруппированный
распределенный
Что распространяется?
Разделив часть системы на отдельный сервис, внутренние сервисы системы могут звонить друг другу, а внешне система все равно образует единое целое
Типичная сцена
Некоторое хранение данных необходимо выполнить во время разработки сервера.Часто мы используем базы данных, такие как mysql, вместо хранения данных в узлах приложения.В настоящее время это фактически простая распределенная система.Приложение читает сетевые протоколы.Запишите базу данных и при этом приложение и база данных вместе образуют единый сервис
Диаграмма архитектуры
кластер
Что такое кластер?
В распределенной системе только что упомянутые, приложения и базы данных, очевидно, обеспечивают различные функции в системе. Когда мы развертываем несколько идентичных узлов приложений, эти узлы приложений образуют кластер приложений. Видно, что кластер является множественным ансамблем узлов, которые обеспечивают та же функция
Типичная сцена
На самом деле, в концепции кластеризации упоминается типичный сценарий, то есть когда мы развертываем приложения узла, особенно в производственной среде, мы обычно развертываем как минимум два узла приложения, чтобы обеспечить более мощные возможности обработки бизнес-данных и снизить затраты. простоя некоторого узла в системе в целом, формируя таким образом кластер приложений
Диаграмма архитектуры
Единая точка отказа, высокая доступность
единая точка отказа
Что такое единая точка отказа
Так называемая единая точка означает, что в системе есть только один узел для службы, такой как наше приложение узла, в это время, если программа дает сбой или сервер выходит из строя, система в целом становится недоступной извне. мире, таким образом образуя единую точку отказа
решение
Одна и та же служба развертывает несколько узлов на нескольких машинах.В это время есть проблема с одной машиной или одной службой, а общая производительность системы все еще доступна для внешнего мира, поэтому кластер серверов приложений, упомянутый выше, уже может решить Эта проблема.
Высокая доступность
Что такое высокая доступность
Система может поддерживать нормальные внешние сервисы в течение длительного времени
решение
Предыдущая единая точка отказа на самом деле является типичной проблемой, которая не позволяет системе достичь высокой доступности, поэтому развертывание нескольких узлов приложений для формирования кластера по-прежнему является основным решением для достижения высокой доступности системы.
плавный выпуск
Что такое гладкая публикация
Когда служба узла выпускается, часто необходимо остановить службу, а затем перезапустить службу с новым кодом.В течение этого периода, если система все еще может поддерживать нормальные внешние службы, это называется плавным выпуском.
решение
Когда в системе есть несколько узлов приложений, фактически выполняются основные условия для плавного выпуска.Например, если в системе развернуты два узла приложений A и B, необходимо только остановить службу узла A и опубликовать узел A и т. д. После освобождения узла A можно таким же образом освободить узел B.
Балансировка нагрузки
Что такое балансировка нагрузки
Как упоминалось выше, при условии, что в системе развернуто несколько узлов приложений, клиентский запрос должен быть распределен службой на каждый узел приложения в соответствии с определенной стратегией, чтобы несколько узлов могли предоставлять услуги внешнему миру. называются нагрузочными для системы, и так называемой балансировкой, то есть использованием определенной стратегии распределения для достижения относительно равномерного распределения клиентских запросов на несколько узлов
решение
Как обычный веб-сервер, nginx на самом деле имеет возможности балансировки нагрузки.Мы можем использовать один nginx в качестве внешнего сервера кластера приложений.nginx может случайным образом распределять запросы на несколько узлов приложений.Конечно, можно настроить и некоторые другие стратегии, например, по хешу ip, распределению по весу узла и т. д.
Диаграмма архитектуры
Постоянное хранилище, кэширование, распределенное кэширование
Что такое постоянное хранилище
Службы, которые могут хранить данные в течение длительного времени, такие как базы данных, такие как mysql, и для обеспечения постоянного хранения обычно должны хранить данные в виде файлов на диске.
что такое кеш
Кэш должен быть знаком учащимся, изучающим интерфейс.Как правило, хранилище с высокой скоростью доступа называется кешем, а узкое место в скорости доступа часто зависит от носителя данных, например постоянного хранилища, которое обычно сохраняет данные в виде файлов на диске. в то время как скорость ввода-вывода файлов на диске, очевидно, намного ниже, чем скорость ввода-вывода в память, поэтому обычно кеш использует память в качестве носителя для хранения, например Redis, или даже напрямую сохраняет данные в объект js в программе node. , что на самом деле является своего рода простым кэшированием
Распределенный кеш
Что такое распределенный кэш
Как было сказано выше, очевидно, что распределенный кеш — это кеш, выделенный в отдельный сервис, например, redis и т.п.
Зачем нужен распределенный кэш
Предполагая, что в нашей системе есть несколько узлов приложения, клиент отправляет запрос на сохранение некоторых данных, а балансировка нагрузки распределяет запрос на узел приложения.В это время, если распределенный кеш не используется, узел кэширует данные в своем собственном процессе узла.В памяти, когда клиент снова запрашивает данные, балансировка нагрузки по-прежнему будет случайным образом распределять запрос на узел приложения, и если узел, получающий запрос в это время, несовместим с предыдущим запросом на хранилище , в узле data нет соответствующего узла, что приводит к сбою извлечения данных. Видно, что для решения подобных задач нам нужно централизованное хранилище кластеров приложений.
решение
После того, как какой-либо узел получает запрос на хранение данных, он сохраняет данные в распределенном кеше, таком как Redis, когда клиент извлекает данные, узел приложения по-прежнему получает соответствующие данные от Redis и отвечает клиенту.
Диаграмма архитектуры
очередь сообщений
Что такое очередь сообщений
Так называемое сообщение на самом деле является данными определенной структуры.Очевидно, что очередь сообщений представляет собой структуру данных FIFO, образованную данными определенной структуры.Обычно для реализации сообщения используется redis или другой более профессиональный mq (очередь сообщений) очередь.
сцены, которые будут использоваться
См. раздел «Асинхронные задачи» непосредственно ниже.
Асинхронные задачи, запланированные задачи
асинхронная задача
Обычным сценарием является то, что наше приложение node предоставляет услуги на основе http для внешнего мира.Система получает http-запрос, выполняет некоторую бизнес-логику, а затем отвечает клиенту через http. Теперь предположим, что бизнес-сценарий — это регистрация пользователя, бизнес-логика сервера должна выполнить ряд операций, таких как создание пользователя, сохранение пользователя в базе данных, отправка электронного письма в почтовый ящик пользователя и т. д. В это время, если все операции выполняются синхронно, а затем реагируют на сообщение. Успешное создание пользователя клиента может занять много времени, а скорость отклика системы является важным показателем взаимодействия с пользователем или производительности системы. Поэтому отложенные данные логики, занимающей много времени и мало влияющей на успех основного бизнеса (например, отправка писем здесь), можно сначала отправить в очередь сообщений на хранение, а затем сразу же ответить клиенту, что пользователь успешно создан, а затем асинхронно Функция FIFO очереди сообщений позволяет обрабатывать эти задачи последовательно в порядке http-запросов
Диаграмма архитектуры
задача на время
Задачи синхронизации просты для понимания.Например, в нашем сервисе узла мы можем запустить некоторые процессы для выполнения некоторых задач в определенный период времени, например, подсчет среднего возраста пользователей, которые заходят в систему один раз в день.
Постоянные соединения и веб-сокеты
Что такое долгое соединение
Проще говоря, когда клиент устанавливает долгосрочное сетевое соединение с сервером, это называется долгим соединением. Общий протокол http, нижний уровень основан на tcp, хотя сам tcp не ограничивает продолжительность соединения, но из-за концепции дизайна самого http как протокола прикладного уровня соединение может быть разорвано после окончания ответа на запрос модель, и когда мы находимся в службе узла. При использовании веб-сокета и клиента для долгосрочной, многократной двусторонней дуплексной связи это можно назвать длинным соединением.
сцены, которые будут использоваться
Как упоминалось выше, когда обрабатываемый бизнес не подходит для решения с помощью простой модели запрос-ответ, а клиенту и серверу необходимо осуществлять долгосрочный, многочастотный двусторонний обмен данными, рассмотрите возможность использования длительного соединение, такое как веб-сокет
Высокий параллелизм
Наконец, давайте кратко поговорим о высоком параллелизме.Так называемый высокий параллелизм относится к сценарию, когда системе необходимо обрабатывать большое количество клиентских запросов одновременно, а наш nodejs использует однопоточный, неблокирующий I/ O с базовой моделью, управляемой событиями. Существуют естественные преимущества (конечно, не абсолютные) при одновременном запросе. Что ж, в этой статье не будет подробно обсуждаться высокий уровень параллелизма в nodejs.Если вам интересно, вы можете обратиться к моей предыдущей статье.nuggets.capable/post/684490…
фактический случай
Распределенное преобразование и многоузловое развертывание интерфейсных унифицированных сервисов упаковки
задний план
Нижний уровень интерфейсной системы публикации компании обеспечивается унифицированной службой упаковки для обеспечения функции упаковки интерфейсных проектов, которая технически представляет собой проект узла, использующий eggjs. Базовая бизнес-логика заключается в том, что клиент инициирует запрос на упаковку, сервер принимает запрос, загружает код проекта из репозитория кода, устанавливает зависимости, выполняет сценарий упаковки и отправляет журналы, сгенерированные в процессе упаковки, клиенту через веб-сокет. , Результат загружается на сервер. См. блок-схему ниже
Поскольку каждая задача упаковки имеет определенное потребление системных ресурсов, таких как процессор, память и т. д., а системные ресурсы имеют верхний предел, в программе поддерживается очередь задач, чтобы гарантировать, что задачи упаковки, обрабатываемые в одно и то же время, выполнятся. не превышать определенного числа, а дополнительные задачи обрабатываются в очереди в порядке FIFO.
Проблемы до ремонта
Сервер приложений развернут на одном узле, что не может обеспечить базовую высокую доступность и плавный выпуск, а также потому, что количество одновременно обрабатываемых задач упаковки зависит от верхнего предела системных ресурсов, а с ростом требований к выпуску фронт- конечных команд по всей компании, явление очередей также увеличивается, что становится все более и более серьезным, влияя на эффективность выпуска интерфейсных проектов всей компании.
Возможное решение и проблема
Поскольку системные ресурсы являются узким местом, можно ли напрямую обновить аппаратные ресурсы системы? Ответ — да, но это не хорошее, простое в реализации и масштабируемое решение. Во-первых, иногда бывает непросто напрямую добавить аппаратные ресурсы, хотя для ее решения можно использовать некоторые технологии виртуализации; во-вторых, если определенное количество системных ресурсов добавляется в соответствии с существующими требованиями, а спрос снова возрастает после период времени, это необходимо сделать снова.Расширение аппаратных ресурсов, очевидно, не является простым в реализации и масштабируемым решением. В то же время одноузловое развертывание приложений не может обеспечить базовую высокую доступность и плавный выпуск, что также в определенной степени влияет на стабильность системы и работу пользователей.
Решение для многоузлового развертывания
Прежде всего, для многоузлового развертывания вам нужно всего лишь развернуть одно и то же приложение на нескольких серверах, а затем использовать nginx для предварительного распределения запросов. Но если бы это было просто так, это вызвало бы серьезные проблемы.
Вопрос 1. Если предположить, что один сервер может обрабатывать 4 задачи упаковки одновременно, то развертывание двух серверов должно иметь возможность обрабатывать 8 задач одновременно. Рассмотрим сценарий: приходит 5 запросов пакетов, при условии, что все они случайным образом распределяются на один и тот же узел приложения с помощью nginx, что произойдет? Узел приложения обработал первые четыре задачи, и после поступления пятой задачи, поскольку превышено максимальное количество задач, которые узел может обрабатывать одновременно, задача помещается приложением в состояние ожидания, т.е. , он входит в логику организации очереди. Что касается системы в целом, то максимальное количество задач, которые могут обрабатываться одновременно, равно 8, но это вызывает очередь при поступлении пятой задачи, что явно не соответствует нашим ожиданиям.
Вопрос 2. Как упоминалось ранее, служба упаковки должна передать сгенерированный журнал клиенту через веб-сокет в процессе упаковки. Рассмотрим сценарий, предположив, что есть два сервера приложений A и B, клиент инициирует запрос пакета, а nginx распределяет запрос на узел A. При этом, поскольку клиенту необходимо получить лог пакета через веб-сокет, клиент инициирует еще один вебсокет Длинное соединение В это время nginx снова раздает и устанавливает длинное соединение с узлом B. Что произойдет? Поскольку в узле B не выполняется задача упаковки и не создается журнал, естественно, что клиент не может получить нужные данные через длинное соединение.
Распределенная трансформация решений
Как видно из вышеприведенного сценария, суть обеих проблем заключается в том, что узел, который применяется в определенном состоянии приложения, поддерживается независимо, что делает систему неспособной формировать извне эффективное целое, поэтому решение состоит в том, что состояние распространяется за пределы кластера приложений, образуя независимую общедоступную службу. Для первого вопроса я использую Redis в качестве распределенного кеша для поддержки очереди задач.После того, как каждый узел приложения получает запрос, он сначала отправляет задачу в очередь задач, и все узлы тянут задачу в соответствии со своими условиями обработки задачи. Это также формирует модель производства/потребления.Каждый узел приложения действует как производитель для создания задач в очереди задач, а также действует как потребитель для извлечения задач из очереди задач для потребления. Таким образом можно гарантировать, что задачи, обрабатываемые каждым узлом одновременно, не превышают его собственного лимита, а внешняя служебная логика системы в целом также находится в норме.
ок, давайте рассмотрим второй вопрос Суть проблемы в том, что nginx не распределяется на узел приложения, соответствующий задаче упаковки при раздаче длинного соединения, поэтому клиент не может получить лог упаковки. Redis также используется для отправки данных журнала, сгенерированных всеми узлами, в redis, а затем для использования функции публикации/подписки redis.Все узлы подписываются на тему, опубликованную журналом заранее.Когда узел публикует новые данные журнала в Redis, все узлы могут получать соответствующие данные журнала от Redis. На данный момент все узлы в кластере приложений имеют возможность отправлять журналы, сгенерированные всеми пакетируемыми в системе задачами.
резюме
На данный момент многоузловое развертывание унифицированных служб упаковки было завершено за счет системной архитектуры распределенных очередей задач, производства и потребления, публикации и подписки на данные журналов, а также кластеров приложений, что обеспечивает базовую высокую доступность и бесперебойную публикацию системы. И такая архитектура играет более важную роль, то есть дает системе возможность горизонтального масштабирования, то есть мы теперь можем плавно развертывать новые узлы приложений в кластере, когда общей сервисной способности системы снова недостаточно. (Так называемое горизонтальное расширение — это вертикальное направление на предыдущей схеме архитектуры. Обычно направление, в котором система простирается от клиента к серверу, называется вертикальным направлением архитектуры системы, а внутренняя часть определенного уровня в вертикальное направление — это горизонтальное направление, например, в нашем кластере приложений выше)
Суммировать
На самом деле проектирование архитектуры как сервера, так и клиента представляет собой постепенный и постепенный процесс улучшения, и часто нет необходимости использовать самую сложную архитектуру, как только она появляется, что может привести к трате ресурсов во всех аспектах. и улучшать систему напрасно.Сложность и другие вопросы, во многих случаях простая и эффективная архитектура, которая может удовлетворить потребности, является хорошей архитектурой. Однако, с другой стороны, проектировщики систем также должны быть дальновидными и иметь возможность делать разумные прогнозы относительно будущего направления развития системы или требований пользователей, чтобы разработать более масштабируемую архитектуру.