Есть ли способ обмена памятью между рабочими/потоками/чем-то в Node.JS?

У меня есть приложение Node, которое обращается к статической, большой ( > 100M), сложной структуре данных в памяти, принимает запросы и затем обслуживает небольшие фрагменты этих данных клиенту через HTTP.

На большинство запросов можно ответить в десятые доли секунды. Ура для Node!

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

Чтобы эффективно обслуживать больше клиентов, я хотел бы использовать какой-то parallelism.

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

Однако, насколько я могу судить, все стандартные способы сделать parallelism в Node явно делают это невозможным. Для безопасности они не хотят, чтобы вы что-то рассказывали.

Но есть ли способ?

Фон:

Неправильно размещать эту структуру данных в базе данных или использовать memcached или что-то в этом роде.

Библиотеки API WebWorker и т.д. позволяют передавать только короткие сериализованные сообщения внутри и вне рабочих.

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

Вероятно, правильным ответом было бы использовать доступ к файловой системе в общую память, например, tmpfs или mmap. Есть несколько библиотек Node, которые делают mount() и mmap() доступными для чего-то подобного. К сожалению, тогда необходимо реализовать комплексный доступ к структуре данных поверх синхронных запросов и чтений. Мое приложение использует массивы массивов dicts и так далее. Было бы неплохо не переопределять все это.

Ответы

Ответ 1

Я попытался написать привязку C/С++ доступа к общей памяти из nodejs. https://github.com/supipd/node-shm

Продолжайте работать (но работайте для меня), возможно, полезно, если ошибка или предложение, сообщите мне.

Ответ 2

Здание с waf - это старый стиль (node 0,6 и ниже), новая сборка с gyp.

Вы должны посмотреть на кластер node (http://nodejs.org/api/cluster.html). Непонятно, что это поможет вам, не имея более подробной информации, но это запускает несколько процессов node на одном компьютере с использованием fork.

Ответ 3

На самом деле Node поддерживает процессы нереста. Я не уверен, насколько близок вилка Node к реальной вилке, но вы можете попробовать:

http://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options

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

Если вам нужно больше памяти - добавьте больше памяти.:) Это так просто. Также вы должны подумать о том, чтобы поместить все эти данные в выделенную базу данных в памяти, такую ​​как Redis или Memcached (или даже Couchbase, если вам нужны сложные запросы). Вам больше не придется беспокоиться о дублировании этих данных.

Ответ 4

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

С этим в сторону...

  • Используйте process.nextTick(возможно, даже вложенные блоки), чтобы удостовериться, что дорогостоящая работа процессора является асинхронной и не позволяет заблокировать ваш поток. Это гарантирует, что один клиент, делающий дорогие запросы, не оказывает негативного влияния на всех остальных.

  • Используйте кластер Node.js, чтобы добавить рабочий процесс для каждого процессора в системе. Рабочие процессы могут привязываться к одному HTTP-порту и использовать Memcached или Redis для совместного использования состояния памяти. У рабочих также есть API сообщений, который можно использовать для синхронизации синхронизированного кэша в процессе работы, однако он имеет некоторые ограничения последовательности.