forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   JavaScript / HTML (http://forum.boolean.name/forumdisplay.php?f=136)
-   -   Node.JS + MongoDB (http://forum.boolean.name/showthread.php?t=18507)

pax 05.09.2013 08:06

Ответ: Node.JS + MongoDB
 
А ты для задержки всегда setTimeout используешь? Я сейчас пользуюсь setImmediate для создания асинхронности. Она вроде откладывает выполнение до следующего цикла.

И еще вопрос: как правильно запускать/останавливать/перезапускать node js на сервере? Я пока только на windows его запускал.

moka 05.09.2013 13:57

Ответ: Node.JS + MongoDB
 
Цитата:

Сообщение от pax (Сообщение 266521)
А ты для задержки всегда setTimeout используешь? Я сейчас пользуюсь setImmediate для создания асинхронности. Она вроде откладывает выполнение до следующего цикла.

Ну если тебе нужно выполнить как можно скорее, но ты хочешь немного распределить нагрузку, то конечно можно.
Но имхо, если у тебя операция на столь тяжёлая и уже потребовала слишком много времени, тогда я советую пересмотреть либо операцию, либо выдвинуть её в отдельный node процесс и общаться с ним через ZeroMQ, тем самым - это будет точно асинхронно (главный процесс не будет выполнять задачу, и сможет паралельно заниматься своими вещами).

Цитата:

Сообщение от pax (Сообщение 266521)
И еще вопрос: как правильно запускать/останавливать/перезапускать node js на сервере? Я пока только на windows его запускал.

Я делал и на win и на unix.
На win, при разработки в Sublime Text 2, есть аддон для настроек компиляции. Тупо - билдишь, и в консоль будет выдаваться консоль. Но нужно дополнительно скрипт для остановки процесса (а то если ты сокет биндишь и не остановишь прошлый процесс, новый не сможет сокет создать на том же порту).
А для деплоймента использовал NSSM ( http://nssm.cc/ ) - Non-Sucking Service Manager - очень понравился. В win редко когда есть хорошие туулзы и минималистичные как в unix. В общем он создаёт сервис в системе, и следит за ним. Можно настроить разные сценарии если процесс сервиса падает - перезапускать например сразу.
Не для всех конечно случаев, но для многих я тупо сделал сервис на текущий разрабатываемый проект, и всё что нужно было, это останавливать процесс, и сервис перезапускал его автоматически так что заместо - остановить > запустить, я только один клик остановки - и уже мог идти тестировать.
Единственное что логи нужно тогда придумать как слать, для этого я winston сделал и отдельный монитор с дашбоардом консоля :)

На linux, есть два способа, первый проще и быстрее - screen. Делаешь отдельный screen и запускаешь там, затем детачишься из скрина если не нужно там быть.
Но лучше конечно написать скрипт для сервиса, плюсов много - логи можно в файл по стандарту выводить. Автозапуск при рестарте компа. Удобно рестартовать: service api restart

Вот файл для скрипта, кладём в /etc/init.d/ я назвал его "api". Работает на RedHat системах и Ubuntu. Естественно замени пути к твоим файлам сам.
service api start
service api stop
service api restart
Логи по стандарту тут: /var/log/api.log

PHP код:

#!/bin/sh

#
# chkconfig: 35 99 99
# name: API
# description: Node.js /var/api/app.js
#

if [ -"/etc/rc.d/init.d/functions" ] ; then
  
. /etc/rc.d/init.d/functions
  USER
="ec2-user"
  
ROOT_DIR="/var/api"
  
LOCK_FILE="/var/lock/subsys/api"
  
LOG_FILE="/var/log/api.log"
else
  . /
lib/lsb/init-functions
  USER
="root"
  
ROOT_DIR="/vagrant"
  
LOCK_FILE="/var/lock/api"
  
LOG_FILE="/var/log/api.log"

  
echo_success() {
    echo -
"[  OK  ]"
    
return 0
  
}
  
echo_failure() {
    echo -
"[FAILED]"
    
return 1
  
}
fi

DAEMON
="/usr/local/bin/node"
SERVER="$ROOT_DIR/app.js"

start() {
  
pid=`ps -aefw | grep "$DAEMON $SERVER" | grep -v "grep " | awk '{print $2}'`
  if [ -
"$pid] ; then
    
echo "$SERVER is already running."
    
RETVAL=1
  
else
    echo -
"Starting $SERVER: "
    
if [ type runuser > /dev/null 2>&] ; then
      runuser 
-"$USER-"$DAEMON $SERVER >> $LOG_FILE &" && echo_success || echo_failure
    
else
      
su "$USER-"$DAEMON $SERVER >> $LOG_FILE &" && echo_success || echo_failure
    fi
    RETVAL
=$?
    echo
    [ 
$RETVAL -eq 0 ]
  
fi
}

stop() {
  echo -
"Stopping $SERVER: "
  
pid=`ps -aefw | grep "$DAEMON $SERVER" | grep -v "grep " | awk '{print $2}'`
  
kill -9 $pid > /dev/null 2>&&& echo_success || echo_failure
  RETVAL
=$?
  echo
  [ 
$RETVAL -eq 0 ]
}

case 
"$1" in
  start
)
    
start
    
;;
  
stop)
    
stop
    
;;
  
restart)
    
stop
    start
    
;;
  *)
    echo 
"Usage: $0 {start|stop|restart}"
    
RETVAL=1
esac

exit $RETVAL 


pax 13.09.2013 12:49

Ответ: Node.JS + MongoDB
 
Я так понял что нельзя обновить несколько членов массива за один запрос?

moka 13.09.2013 14:19

Ответ: Node.JS + MongoDB
 
Почему нет?
Под обновить - что ты имеешь ввиду конкретно?

Тест - обновляет:
PHP код:

mongo
> use test
db.items.insert({ a: [ 1] })
db.items.find()
"_id" ObjectId("5232d861f37cb58b0486eeb1"), "a" : [  1,  ] }
db.items.update({ }, { $set: { 'a.0'5'a.1'} })
db.items.find()
"_id" ObjectId("5232d861f37cb58b0486eeb1"), "a" : [  5,  ] } 


pax 13.09.2013 14:40

Ответ: Node.JS + MongoDB
 
Мне надо у каждого объекта в массиве обновить поле или несколько полей. А не каждый итем обновлять по индексам.
Я пробовал такой запрос:
PHP код:

db.collection('users').update({_idparams.requester'items.robot'robotId},
       {
$unset: {'items.$.robot'0'items.$.slot'0}}, function () {}); 

Но обновляет всего одну запись в массиве.

в итоге наткнулся на это:
https://jira.mongodb.org/browse/SERVER-1243

moka 13.09.2013 15:32

Ответ: Node.JS + MongoDB
 
А оператор $ да, обновит только первый найденный элемент в твоём случае..

Выход будет - подгрузить, выбрать в JS то что нужно, и обновить уже с новым списком.

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

pax 19.09.2013 12:16

Ответ: Node.JS + MongoDB
 
Получил вот такое:


Как с этим бороться?

moka 19.09.2013 14:00

Ответ: Node.JS + MongoDB
 
ETIMEDOUT это системная ошибка, а не самого node.js, видимо что-то на уровне TCP происходит, а node.js просто продвигает её.

Нужно знать как ты добиваешься такой ошибки, т.к. я на практике её не встречал.

Если хочешь избежать падения процесса, можешь попробовать её поймать, возможно есть event для сокета (т.к. возможно ты с сокетами это ловишь):
PHP код:

socket.on('error', function(err) {
  
console.log(err);
  
console.log(err.stack);


А если нету, то нужно ловить unhandledException: http://nodejs.org/api/process.html#p...aughtexception
В продакшане очень не рекомендуется - т.к. это будет ловить не пойманные ошибки, но при этом оставлять процесс жить, когда последствия ошибки могут быть "не желательными".

pax 19.09.2013 15:08

Ответ: Node.JS + MongoDB
 
Поставил обработчик пока на unhandledException.

Как оно получается я пока не знаю.
У меня сейчас два процесса, т.к. я использую кластер на одном ядре виртуального сервера. REST API на основе express (http и https) в воркере. В мастере я запустил модуль cron, по которому я подсчитываю и обновляю статистику (это только подключение к MongoDB и асинхронное обновление). Других операций с сокетами я не делаю...

pax 19.09.2013 15:40

Ответ: Node.JS + MongoDB
 
Запустил у себя на сервере наконец по дефолту вместо апача node js и думаю сейчас... а есть ли какой-то миддлваре для express, который может переадресовать для определенных хостов запрос на другой порт сервера, где запущен апач...? Если я вдруг захочу для дочернего домена сделать сайтик на php и использовать его на дефолтном порту...

moka 19.09.2013 16:19

Ответ: Node.JS + MongoDB
 
Есть, только его лучше использовать до главного API приложения.
http-proxy - проксит всё, вплоть до вебсокетов.

Шустрый и используется nodejistu (хостинг node).
https://github.com/nodejitsu/node-http-proxy

Там всё по сути просто. Пишешь мелкий proxy app на ноде, указываешь разные прокси куда и как раскидывать, там есть куча вариантов проксить, вплоть до ручного определения.

Получается запускаем proxy на 80 порту, далее API на другом, и проксим к API по дефолту.
Apache запускаем тоже на другом порту, и проксим на него тоже по субдомену (например), а можно и по субдиректории.

Если юзаешь AWS советую заюзать Route53 - домен менеджер, создание субдомена и обновление DNS записей занимает пару минут а не сутки.

pax 24.09.2013 11:21

Ответ: Node.JS + MongoDB
 


Что-то не могу составить запрос на удаление поля HandR

UPD: получилось

PHP код:

var unset = {};
    unset[
'items.$.slots.' slotName] = 1;
    
db.collection('users').update({_idparams.requester'items.id'robotId}, {$unset: unset}, function (errres) {

    }); 


pax 27.09.2013 19:55

Ответ: Node.JS + MongoDB
 
moka А не можешь ли привести пример простенького реалтаймового сервера, передающего координаты игроков. Я бы хотел node js и Unity связать через TCP.

moka 27.09.2013 20:17

Ответ: Node.JS + MongoDB
 
Примеры есть, только они на socket.io, следственно там только игровая логика и никакой сетевой, т.к. всё уже сделано используя socket.io. Но, естественно можно и сделать сериализацию и десериализацию на обоих сторонах. Проще будет начать с JSON'а, а потом что-то придумать дельнее.

Вот немного говнокода, писалось 24 часа, потом чуток приводилось в порядок но совсем чуток.
https://github.com/Maksims/beat-em-up
Играть тут: http://moka.co:88/

UPD:
Я не советую, но есть socket.io клиент для unity: https://github.com/NetEase/UnitySocketIO

pax 01.10.2013 12:38

Ответ: Node.JS + MongoDB
 
Не пойму как выполнить поиск с использованием регулярных выражений и символов юникода (русский текст).

Получилось,
PHP код:

db.collection('collection_name').find({name_upper: /.*pattern.*/i}).toArray(function(errdocuments){

}); 



Часовой пояс GMT +4, время: 22:01.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot