These are chat archives for NodejsRUS/chat

7th
Mar 2016
Михаил
@muxahuk
Mar 07 2016 14:20 UTC
Проблема в том, что запуская child_process я не могу передать и все остальные параметры... т.е. указатели на память, где храняться нужные объекты.. У меня получается есть какой-то массив объектов, я хочу часть выполнить на 1-м проц., другую на другом и затем продолжить работу с этим массивом в мастере. У меня проблема передать в чайлд процесс объекты, с которыми нужно работать, функцию, которую нужно запускать для каждого объекта
@JustBlackBird @imposibrus
Vadim Petrov
@imposibrus
Mar 07 2016 14:33 UTC
@muxahuk ага, я пару лет назад искал что-то подобное, но остановился на том, что шарить память между воркерами не получается. точнее есть модули для шаринга, но они сериализуют все данные при приеме/передаче (JSON.stringify() - считай можно передать только примитивы, никаких объектов с методами).
посмотрите на webworker-threads. с помощью него можно передавать аргументы в воркер. т.е. вы сможете сначала объявить функцию-воркера, а потом передавать туда данные и ждать ответа, когда она завершится.
я думаю, что на текущий момент только так.
Ivan
@IvanMMM
Mar 07 2016 14:45 UTC
А Process.send чем вам не нравится?) По моему он передаёт сам объект, не восстанавливая его из строки.
А вообще более правильный способ - отправлять воркера только айдишку объекта(из базы, к примеру) и потом получать его заново.
Vadim Petrov
@imposibrus
Mar 07 2016 14:47 UTC
@IvanMMM насколько я помню, он умеет только объект http-сервера так передавать. хотя.. надо проверить)
Ivan
@IvanMMM
Mar 07 2016 14:48 UTC
По крайней мере я так делаю и с монгой и с вебсокетами
Vadim Petrov
@imposibrus
Mar 07 2016 14:49 UTC

А вообще более правильный способ - отправлять воркера только айдишку объекта(из базы, к примеру) и потом получать его заново.

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

Ivan
@IvanMMM
Mar 07 2016 14:50 UTC
Да, не самый простой кейс)
В качестве хака можно передавать тело функции
И потом собирать его заново
Ivan
@IvanMMM
Mar 07 2016 14:56 UTC
@muxahuk, а не пробовали kue? Задания могут выполняться парпллельно на любом количестве ядер и даже в кластере, на удалённых машинах. По выполнении заданий можно собрать все данные в кучу и делать с ними что угодно.
Vadim Petrov
@imposibrus
Mar 07 2016 14:59 UTC

@IvanMMM я правильно делаю?
app.js:

var child_process = require('child_process'),
    worker = child_process.fork('./testWorker.js');

worker.send({
  asd: 'qwe',
  log: function() {
    console.log(Array.from(arguments));
  }
});

worker.js

process.on('message', function(data) {
  console.log('worker received', data);
  console.log('log', data.log);
});

в консоль выводит:

worker received { asd: 'qwe' }
log undefined

node --version
v5.0.0

Михаил
@muxahuk
Mar 07 2016 15:03 UTC
вот у меня такая-же проблема с моим кодом - не передаются функции и объекты ( классы ) в worker
а мне по сути нужно запустить events.emit( 'custom_event', user ); в воркере ( ну и собственно, что бы все события on('custom_event') выполнились в воркере..
Kyrylo Yakovenko
@blia
Mar 07 2016 15:05 UTC
new Function? :)
Ivan
@IvanMMM
Mar 07 2016 15:11 UTC
Ну если речь именно о воркере, то самый надёжный вариант - восстанавливать объект по айдишке из базы или откуда он там взят. Без танцев с бубном по крайней мере. Если речь о каком-нибудь стороннем приложении тогда тут не обойтись без магии.
В вашем случае может идти речь о переносе логики создания функции с мастера на воркера. Те отдавать воркеру только параметры функции.
Михаил
@muxahuk
Mar 07 2016 15:13 UTC
проблема вся в том... может я конечно не правильно вообще всё делаю..
вообщем задача полностью:
Ivan
@IvanMMM
Mar 07 2016 15:13 UTC
Я просто боюсь что нода не шарит память между процессами. А без этого все указатели бесполезны.
Михаил
@muxahuk
Mar 07 2016 15:13 UTC
он не шарит
это 100%
Ivan
@IvanMMM
Mar 07 2016 15:14 UTC
Тогда как вариант искать решение этой проблемы. Я около года назад искал что то подобное. Не помню чтобы нашёл какое-то решение.
Михаил
@muxahuk
Mar 07 2016 15:14 UTC
так вот, задача: мультипользовательсая игра, чел-к заходит на сервер ( хттп ) выбирает сервер ( игровой ) получает ип и соединяется по сокету с ним ( с игровым ).
Ivan
@IvanMMM
Mar 07 2016 15:15 UTC
Есть низкоуровневые решения, но они оверхед, имхо.
Михаил
@muxahuk
Mar 07 2016 15:15 UTC
Проблема в том, что если заходят 3 и более играков нагрузка на игровой сервер 80% ( цпу )
на 1 проц.
я думал решить это распаралеливанием пользователей ( аля форк )
Ivan
@IvanMMM
Mar 07 2016 15:16 UTC
Тут нужен лоад балансер обычный.
Михаил
@muxahuk
Mar 07 2016 15:16 UTC
но тогда пользователи не видят друг друга т.к. обхект который содержит всех пользователей - разный
т.е. на 1-й форк зашло 5 человек онии видят друг друга, на 2-й 3 чел-ка - они не видят тех 5-ть, а только 3-х..
Ivan
@IvanMMM
Mar 07 2016 15:18 UTC
Храни главный объект на Мастере, а воркеры могут просто сообщать мастеру обновления.
И брать нагрузку по обработке данных на себя.
Михаил
@muxahuk
Mar 07 2016 15:19 UTC
вот я это и хотел сделать.. пробовал child_process
Ivan
@IvanMMM
Mar 07 2016 15:19 UTC
Соответсвенно не будет смысла сообщать юзеру айпишник воркера
Vadim Petrov
@imposibrus
Mar 07 2016 15:19 UTC
@muxahuk у вас, наверное, socket.io?) у меня так руки и не дошли переписать кусок их ядра под свою похожую задачу, чтобы можно было иметь доступ к данным сокетов на разных инстансах)
Ivan
@IvanMMM
Mar 07 2016 15:20 UTC
Будет один главный сервер который сможет изменять нагрузку на воркеров в реалтайме, а сам отдавать данные.
Михаил
@muxahuk
Mar 07 2016 15:20 UTC
но в него не получается передать массив от Мастера со всеми пользователями... или с частью..
@imposibrus да, socket.io...
у меня вся система построена на событиях ( EventEmitter ), что бы любой модуль ( подмодуль ) мог расширить функционал в том месте где ему нужно
тут то и возникает проблема...
Ivan
@IvanMMM
Mar 07 2016 15:22 UTC
У них есть модуль хороший, который реализует общий пул подключений через редиску. Называется socket.io-redis
Точнее это адаптер) в общем полезная штука.
Те фактически надо чтобы эвент на воркере тригерил событие на мастере?
Михаил
@muxahuk
Mar 07 2016 15:24 UTC
угу, но при этом выполнял событие на воркере, не нагружая мастер
Ivan
@IvanMMM
Mar 07 2016 15:26 UTC
Сейчас у тебя такая архитектура что каждый воркер-отдельный сервер. В этой реализации можно шарить главный объект через репликацию базы данных, но проще хранить главный объект на мастере и просто обновлять его через process.send с необходимыми данными.
Будет один игровой сервер и сколько хочешь воркеров.
Плюс динамическая нагрузка на воркеров.
И если воркер сдох то главный объект не тронут, нагрузка ложится на других воркеров. А если сдох сервер-воркер то это дисконнект для игроков и потеря игровых данных.
Михаил
@muxahuk
Mar 07 2016 15:30 UTC
events.on( 'player:move', ( socket, point ) => {
    const player = world.getPlayer( socket.id );
    player.moveTo( point );
    player.checkCollisions();
} ); // Такие функции ( события ) подключаются по несколько раз ( с разными функциями ) из разных подмодулей
// world - объект который содержит всех пользователей и все детали мира их расположение и т.п.

///....

_.each( sockets, socket => {
    events.emit( 'player:move', socket, point );
} );
ультрированно но как-то так работает сейчас, без воркеров без ничего ( и нагрузка около 80% на цп )
мне вот нужно сказать воркеру, например у меня 4 пользователя онлайн и 4 ярдра - значит на каждое ядро раскинуть по пользователю и сказать выполнить events.emit( 'player:move', socket, point ); при этом всё что в events.on( 'player:move'....) тоже должно быть выполнено на воркере
Ivan
@IvanMMM
Mar 07 2016 15:35 UTC
Вместо эмита делай process.send и обрабатывай все на мастере.
Блин, давай завтра в скайпе созвонимся) Сейчас бежать надо
Михаил
@muxahuk
Mar 07 2016 15:36 UTC
если что пиши тут ( в лс ), если не найду решения, то созвонимся
Dmitriy Simushev
@JustBlackBird
Mar 07 2016 15:45 UTC
@muxahuk у тебя идеологически неправильная архитектура. node.js однопоточный, а то что ты хочешь сделать требует многопоточности в рамках одного процесс. только тогда можно эффективно шарить данные.
@muxahuk вместо всех этих костылей, проще использовать общее хранилище для разделяемых данных + пачку идентичных node.js приложений-серверов + лоад балансер вроде nginx
для общего хранилища имеет смысл использовать что-нибудь с pub/sub. думаю redis сгодиться
и не надо ничего ручками никуда передавать. изменилось разделяемое состояние -- пуш в редис. все остальные получат нотификацию. (а можно и без нотификаций обойтись, если каждый раз выбирать данные при обработке пользовательского запроса)
короче это типовая схема горизонтального маштабирования воркеров с одной бд
Ivan
@IvanMMM
Mar 07 2016 15:49 UTC
Я бы поставил лайк, но сами понимаете)
Dmitriy Simushev
@JustBlackBird
Mar 07 2016 15:49 UTC
понимаю что?)
Maxim Zavitaev
@MaximZavitaev
Mar 07 2016 15:53 UTC
@muxahuk посмотрите в сторону Impress Application Server. на нем можно запустить несколько воркеров на одном сервере и несколько серверов соединить в один. При этом реализован балансировщик нагрузки, горячая подмена логики(без перезагрузки сервера)
Михаил
@muxahuk
Mar 07 2016 16:43 UTC
интересно, а почему node не делали мультипоточным ?.. какие ограничения там стоят ( яли ) что решили делать однопоточный ? В плане я понимаю что сам js однопоточный, но ведь можно было сделать, что бы он был многопоточным в node, не ?
Ivan
@IvanMMM
Mar 07 2016 16:57 UTC
Движок v8 это движок хрома. собственно они и преследовали свои интересы
Dmitriy Simushev
@JustBlackBird
Mar 07 2016 18:05 UTC
многопоточный js уже не был бы js. ну и 90% случаев реальная многопоточность не так нужна как кажется