Вопрос

Я начал Tinkering с Node.js HTTP-сервером и действительно любите запись сервера JavaScript, но что-то удерживает меня от начала использовать Node.js для моего веб-приложения.

Я понимаю всю концепцию Async ввода / вывода, но я несколько обеспокоен краевыми случаями, когда процедурный код очень интенсивно CPU, таких как манипуляция изображений, либо сортировка больших наборов данных.

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

Одним из предположений было использование веб-работников для интенсивных задач CPU. Тем не менее, я боюсь, что веб-работники сделают его трудно написать чистый код, поскольку он работает, включая отдельный файл JS. Что, если интенсивный код CPU находится в методе объекта? Это вроде отстой, чтобы написать файл JS для каждого метода, который является интенсивным процессором.

Другое предложение было созданию ребенка, но это делает код еще менее поддерживаемым.

Любые предложения по преодолению этого (воспринимаемого) препятствия? Как пишете чистый объектно-ориентированный код с Node.js, когда убедитесь, что тяжелые задачи CPU выполняются Async?

Это было полезно?

Решение

Что вам нужно, это очередь задач! Перемещение ваших длинных рабочих задач из веб-сервера - это хорошо. Сохранение каждой задачи в «отдельном» файле JS продвигает модульность и повторное использование кода. Это заставляет вас думать о том, как структурировать вашу программу таким образом, чтобы облегчить отладочную и поддерживать в долгосрочной перспективе. Еще одно преимущество очереди задач - рабочие могут быть написаны на другом языке. Просто поп выполните задание, выполните работу и напишите ответ на ответ.

что-то вроде этого https://github.com/resque/resque.

Вот статья из Github о том, почему они построили его http://github.com/blog/542-introducing-resque.

Другие советы

Это недоразумение определения веб-сервера - он должен использоваться только для «разговоров» с клиентами. Тяжелые нагрузки должны быть делегированы на санкционные программы (конечно, можно также быть написано в JS).
Вы, вероятно, скажете, что это грязно, но я уверяю вам, что процесс веб-сервера, застрявший в измесении изображений, просто хуже (даже для сказки Apache, когда он не блокирует другие запросы). Тем не менее, вы можете использовать общую библиотеку, чтобы избежать резервирования кода.

Редактировать: Я придумал аналогию; Веб-приложение должно быть в качестве ресторана. У вас есть официанты (веб-сервер) и повара (рабочие). Официанты в контакте с клиентами и выполняют простые задачи, такие как меню, или объясняя, если какое-нибудь блюдо вегетарианское. С другой стороны они делегируют более сложные задачи на кухню. Поскольку официанты делают только простые вещи, которые они реагируют быстрее, и повара могут сосредоточиться на своей работе.

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

Вы не хотите, чтобы ваш интенсивный код CPU выполнить Async, вы хотите его выполнить в параллели. Отказ Вы должны получить обработку работы из потока, которые обслуживают HTTP-запросы. Это единственный способ решить эту проблему. С Nodejs ответ модуль кластера, Для нерестищих детей процессов сделать тяжелую подъем. (Узел AFAIK не имеет никакой концепции потоков / общей памяти; это процессы или ничего). У вас есть два варианта того, как вы структурируете свое приложение. Вы можете получить решение 80/20, неренив 8 HTTP-серверов и обработка вычислительных задач синхронно на дочерние процессы. Делать это довольно просто. Вы можете занять час, чтобы прочитать об этом по этой ссылке. На самом деле, если вы просто отрываетесь от примерного кода в верхней части этой ссылки, вы получите 95% от дороги там.

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

Я удивлен, что ни один из этих других ответов даже упомянуть кластер.

Фон: асинхронный код - код, который приостанавливает, пока что-то не произойдет где-нибудь еще, в какой момент код просыпается и продолжает выполнение. Один очень распространенный случай, когда что-то медленное должно происходить где-то еще, есть в I / O.

Асинхронный код не полезен, если это Ваш процессор Это отвечает за работу. Это именно тот случай с «вычисляющими интенсивными» задачами.

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

Ожидание ввода / вывода - это шаблон, который всегда происходит на веб-серверах, например. Каждый клиент, который соединяется с вашим Севером, получает розетку. Большую часть времени розетки пустые. Вы не хотите ничего делать, пока сокет не получает некоторые данные, в какой момент вы хотите обрабатывать запрос. Под капотом HTTP-сервер, такой как узел, использует библиотеку событий (Libev), чтобы отслеживать тысячи открытых розеток. ОС уведомляет Либев, а затем Libev уведомляет Nodejs, когда один из розетков получает данные, а затем Nodejs ставит событие в очередь события, и ваш HTTP-код пинается в этой точке и обрабатывает события один за другим. События не ставят в очередь, пока сокет не имеет некоторых данных, поэтому события никогда не ждут данных - это уже для них.

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

Пара подходов вы можете использовать.

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

WebWorkers может работать для ваших асинхронных процессов, но в настоящее время они не поддерживаются Node.js. Есть пара расширений, которые обеспечивают поддержку, например: http://github.com/cramForce/node-worker.

Вы все еще получаете все равно повторно использовать модули и код через стандарт «Требуется» механизм. Вам просто нужно убедиться, что первоначальная отправка рабочему передает всю информацию, необходимую для обработки результатов.

Использовать child_process это одно решение. Но каждый дочерний процесс породился, может потреблять много памяти по сравнению с goroutines

Вы также можете использовать решение на основе очереди, такое как kue.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top