Javascript-форум (https://javascript.ru/forum/)
-   Оффтопик (https://javascript.ru/forum/offtopic/)
-   -   Серверный JS (https://javascript.ru/forum/offtopic/22096-servernyjj-js.html)

Андрей Параничев 11.10.2011 22:51

Я в данный момент пишу приложение для социальных сетей на Node.js.

Gozar 12.10.2011 19:17

Цитата:

Сообщение от Андрей Параничев (Сообщение 130832)
Я в данный момент пишу приложение для социальных сетей на Node.js.

Если можно, то подробнее. Почему был выбран Node.js для этого, с чем сравнивался при выборе и что за приложение(тип)?

B~Vladi 12.10.2011 19:20

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

x-yuri 12.10.2011 19:50

а оно запросы случайно не в одном потоке обрабатывает?

Magneto 12.10.2011 19:56

Цитата:

Сообщение от x-yuri
а оно запросы случайно не в одном потоке обрабатывает?

Это что сарказм? В одном потоке, но если я не ошибаюсь то есть вебворкеры и возможность запуска несколько процессов по числу процессоров.

Андрей Параничев 12.10.2011 20:15

Gozar,
Приложение игровое. Был выбран Node.js потому что мне так удобнее, меня устраивает производительность v8 (судя по тестам на сайте апачи, например) и реализация некоторых библиотек (mongoose, socket.io). К тому же разделение по игровым серверам у меня делается через pub/sub от redis сейчас, но поменяю на MQ какой-нибудь скоро, если не будет устраивать производительность. В общем, мне почти нечего сказать кроме того, что проблем почти нет.

Цитата:

А я пытаюсь доказать себе, что на ноде можно делать простые сайты, а не только как AJAX-бекенд.
Можно, просто многое нужно будет написать самому, или собирать по кускам. Express.js меня не устраивает почти полностью и целиком. А отдельно вам понадобится даже обработчик multipart/form-data, потому что по-умолчанию в ноде его нет вообще.

Kolyaj 12.10.2011 21:39

Цитата:

Сообщение от x-yuri
а оно запросы случайно не в одном потоке обрабатывает?

В одном, в этом вся прелесть.

Цитата:

Сообщение от B~Vladi
А я пытаюсь доказать себе, что на ноде можно делать простые сайты, а не только как AJAX-бекенд.

Взять нормальный роутер, взять нормальный шаблонизатор, и можно делать.

Цитата:

Сообщение от Андрей Параничев
Express.js меня не устраивает почти полностью и целиком.

А чем не устраивает? А то я как раз собрался на него переходить со своего велосипеда.

B~Vladi 12.10.2011 21:56

Я не использую фреймворки.
Я сделал так:
Перед нодой поставил nginx. Конфиг:
Код:

// Запросы на неизвестные поддомены отправляем на сервер 404
server {
        listen 80;
        server_name *.amxhost.ru;

        location / {
                proxy_pass http://amxhost.ru:8000/;
                proxy_set_header Host $host;
                proxy_set_header Error 404;
        }
}
// Основной домен
server {
        listen 80;
        server_name amxhost.ru www.amxhost.ru;

        location / {
                proxy_pass http://amxhost.ru:8001;
                proxy_set_header Host $host;
        }
}
// Поддомен
server {
        listen 80;
        server_name ajax.amxhost.ru www.ajax.amxhost.ru;

        location / {
                proxy_pass http://amxhost.ru:8002;
                proxy_set_header Host $host;
        }
}

Т.е. на ноде мы создаем несколько серверов на разных портах:
var CONFIG = require('config');
var SERVERS_PATH = module.filename.replace(/(.*)\/.*$/, '$1/servers');

var LIB = {
	http: require('http'),
	fileSystem: require('fs')
};

// Create servers
LIB.fileSystem.readdir(SERVERS_PATH, function(err, files) {
	if (err) {
		console.log(err);
	} else {
		var length = files.length;
		while (length--) {
			var serverData = files[length].match(/^([^\.]+).js$/);
			if (serverData) {
				var server = module.exports[serverData[1]] = require(SERVERS_PATH + '/' + serverData[0]);
				LIB.http.createServer(server).listen(server.port, CONFIG.host);
			}
		}
	}
});

Это модуль создания серверов. Рядом в папке servers лежат их реализации:
module.exports = function(request, response) {

};
module.exports.port = 8001;

Например, реализация сервера www (обслуживает основной домен), далее делится на сервисы и, в зависимости от запроса, запускается тот или иной сервис.
Всё вроде логично, функционал разделён. Никаких велосипедов писать не пришлось.

Андрей Параничев 12.10.2011 22:45

B~Vladi,
Как у вас обрабатывается multipart/form-data и, собственно, загрузка файлов на хост с клиента? Если никак, рекомендую formidable использовать. Быстрая и стабильная библиотека.

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

Кстати, просто на всякий случай, если у вас в сервере передается Content-Length в заголовке ответа, а результат перед выводом строка в utf-8, то значением заголовка должно быть не {String}.length, а Buffer.byteLength({String}, "utf8"), иначе ответ может быть принят браузером не полностью.

Андрей Параничев 12.10.2011 22:49

Цитата:

Сообщение от Kolyaj (Сообщение 130944)
А чем не устраивает? А то я как раз собрался на него переходить со своего велосипеда.

Некрасивый он, и по внутреннему коду и по тому коду, что я должен под него писать. Он не очень красиво разбивается на отдельные скрипты, т.е. я не могу сконфигурировать его так, чтобы "контроллеры" я мог удобно выносить в разные модули. У меня такое ощущение, что его писали не рассчитывая, что на нем будут писать что-то большое. А так, это вроде web.py, только на ноде. Так что я написал половину велосипеда, потом бросил, потому что текущие задачи не требуют роутинга через основной сервер (у меня и туда и обратно данные передает socket.io).

B~Vladi 12.10.2011 23:10

Цитата:

Сообщение от Андрей Параничев
загрузка файлов на хост с клиента?

Ещё до этого не дошел.
Цитата:

Сообщение от Андрей Параничев
модули придется располагать на разных портах

Вот тут не понял, физически распологать?
Цитата:

Сообщение от Андрей Параничев
значит проблема роутинга у вас не решена вообще

Где про это почитать?
Цитата:

Сообщение от Андрей Параничев
Кстати, просто на всякий случай

Спасибо, буду иметь ввиду.

Андрей Параничев 12.10.2011 23:42

B~Vladi,
У вас эти сервера запускаются на разных портах, а из nginx к ним прокси пасс с субдоменов. Т.е. фактически это максимум можно назвать виртуальными хостами. Но внутри сервера вы как выбираете, какой код будет запускаться, вот у меня например было что-то такое:
Framework({
	"/upload/(\s+)": {
		"json": function(id) {
			return false;
		},
		"html": {
			"get": function(id) {
				this.error(404);
			},
			"post": function(id, postData) {
				return true;
			}
		}
	}
});

Ну это очень примерно.

B~Vladi 13.10.2011 00:22

Так:
module.exports = function(request, response) {
	var serviceName = request.url.match(/^\/([^/]+)/);
	if (serviceName) { // URL состоит из: domain.ru/serviceName/serviceData[/./././]
		serviceName = serviceName[1];
		if (serviceName != 'index' && SERVICES.hasOwnProperty(serviceName)) {
			SERVICES[serviceName](request, response);
		} else { // Если запрос приходит на неизвестный сервис, вызываем код сервера ошибок
			request.headers.error = 404;
			LIB.server.error(request, response);
		}
	} else { // Если имя сервиса отсутствует, вызывается сервис index (главная)
		SERVICES['index'](request, response);
	}
};

module.exports.port = 8001;

// Инициализация сервисов. Так же оформенны в виде модулей.
LIB.fileSystem.readdir(CONFIG.path.services, function(err, files) {
	var length = files.length;
	while (length--) {
		var serviceData = files[length].match(/^([^\.]+).js$/);
		if (serviceData) {
			SERVICES[serviceData[1]] = require(CONFIG.path.services + '/' + serviceData[0]);
		}
	}
});

Этого вполне достаточно.
А о каких проблемах роутинга речь?

x-yuri 13.10.2011 01:50

Цитата:

Сообщение от x-yuri
а оно запросы случайно не в одном потоке обрабатывает?

Цитата:

Сообщение от Magneto
Это что сарказм? В одном потоке, но если я не ошибаюсь то есть вебворкеры и возможность запуска несколько процессов по числу процессоров.

я в общем-то думал о том, что в случае multithreaded/multiprocess веб-сервера, один запрос не может приостановить весь веб-сервер. Не знаю, насколько это аргумент.

Цитата:

Сообщение от Kolyaj
В одном, в этом вся прелесть.

ну это с точки зрения, что не надо синхронизировать

Цитата:

Сообщение от B~Vladi
Вообще если честно я не понимаю, почему говорят что нода для этого плохо подходит.

а какие аргументы?

Цитата:

Сообщение от Андрей Параничев
Некрасивый он, и по внутреннему коду и по тому коду, что я должен под него писать

хм, неужели jquery красивый внутри?

Цитата:

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

он основан на sinatra. Его сегодня один человек назвал микрофреймворк. Не знаю точно, что это означает, но он определенно минималистичен. Писали его с расчетом быстрого создания приложений с минимальными усилиями. Т.е. sinatra даже называет себя не фреймворком, а DSL. Можно ли на нем писать что-то большое... не знаю, не пробовал.

B~Vladi 13.10.2011 08:49

Цитата:

Сообщение от x-yuri
а какие аргументы?

Я точно не помню, сложилось такое впечатление.
Недавно на GDD с одним знакомым PHP-кодером состоялся примерно такой диалог:
Я: Я проект на ноде делаю.
Он: Нода же не для этого? Под неё можно только чаты писать.
Я: Почему?
Он: Ну там же асинхронный код, коллбеки везде?
Я: Ну и что?
Он: Ну как ты будешь писать сайт в асинхронном стиле? Это же сложно?
Я: Ну да, сложнее чем синхронный. Берёшь руками и пишешь. Главное шаблонизатор хороший иметь.

В общем он так и не согласился со мной и аргументов никаких конкретных не назвал. Мне и самому интересно, почему же он плохо подходит.

Kolyaj 13.10.2011 11:55

Цитата:

Сообщение от B~Vladi
В общем он так и не согласился со мной и аргументов никаких конкретных не назвал. Мне и самому интересно, почему же он плохо подходит.

Потому что очень сложно PHP-шные мозги (без всякого негатива термин) перестроить на асинхронный JavaScript.

systemiv 13.10.2011 21:36

А как Вы относитесь к реляционным БД в mySql?
Или лучше NoSql?

B~Vladi 13.10.2011 22:16

Цитата:

Сообщение от systemiv
А как Вы относитесь к реляционным БД в mySql?

Глупость написал.

x-yuri 13.10.2011 22:37

Цитата:

Сообщение от systemiv
А как Вы относитесь к реляционным БД в mySql?

ты действильено думаешь, что nosql всегда лучше? Или mysql всегда лучше? Реляционные БД делают упор на целостность и доступность, а nosql-системы на устойчивости к разделению и доступности (теорема САР)

systemiv 13.10.2011 22:47

Сори, я хотел написать в node
x-yuri, не всегда. Но в каких случаях, лучше использовать mySql или например MongoBD

x-yuri 13.10.2011 23:50

Цитата:

Сообщение от systemiv
Но в каких случаях, лучше использовать mySql или например MongoBD

это следует из того, что я сказал. Если тебе важна целостность данных, выбирай реляционные БД. Можешь еще почитать, что пишут на сайте mongodb

vflash 14.10.2011 01:13

Цитата:

Сообщение от systemiv
mySql или например MongoBD

делали в начале года проект. MongoBD была выбрана потому как предполагалось что будет много данных и их будет с каждым днем все больше. ставка делалась на ее возможность расширяться, мапредьюс итд. в итоге так и не полетела. Притом что нагрузка была только от 1-2х пользователей (я пользовался мож еше кто) через пол года стала нереально тормозить. а ведь предполагалось что проектом будут пользоваться миллионы.

в MongoBD нехватало функционала, потому приходилось извращаться. код представлял из себя адовую смесь перла+js+json+монги. мапредьюс там тормазной и не полностью реализован, редьюс делается на мастере. с индексами там тоже проблемы, составные индексы както странно себя вели и в итоге стали использовать индекс по одному полю. кстати индексы задаются хешом а не массивом тоесть {name: 1, age: 1} , это непривычно странно, так как стандарт js не гарантирует последовательность параметров в хеше.

в MongoBD много магии, сырой и довольно странный API .

x-yuri 14.10.2011 03:42

возможно неподходящая задача или неподходящая реализация, все же mongodb - нереляционная БД и как бывает с ЯП, можно по инерции неправильно ее использовать.

Цитата:

Сообщение от vflash
мапредьюс там тормазной

а где не тормозной и есть опыт работы с другими подобными БД?

Gvozd 14.10.2011 04:29

Цитата:

Сообщение от Kolyaj
Потому что очень сложно PHP-шные мозги (без всякого негатива термин) перестроить на асинхронный JavaScript.

Не у всех так =)
PHP для меня основной язык программирования, что не мешает мне извращаться на нем в асинхронном стиле, причем успешно.

О Node.Js:
что мне нравится в этой модели, кроме асинхронной обработки, и ништяками производительности в связи с этим, так это то, что процесс имеет глобальную область, позволяющую эффективно кешировать куски кода, и результаты функций, и использовать при генерации многих страниц.
В стандартной же модели web-а, процесс отвечает за отрисовку только одной страницы, и кешировать может только вовне. Это всегда медленней, чем глобальный объект кеша в рамках процесса.

Надо украсть идею, и написать свой Node.PHP =)))

Kolyaj 14.10.2011 09:05

Цитата:

Сообщение от Gvozd
Надо украсть идею, и написать свой Node.PHP =)))

А fast-cgi это не то?
Если нет, то какое-то другое решение есть, но вроде PHP там безбожно течёт, т.к. не приспособлен под такое.

vflash 14.10.2011 11:11

x-yuri, когда речь о MongoBD так всегда и говорят. не та задача и не так готовите.

мапредьюс должен распределяться по кластеру. а у них свертка делается на мастере.

Gvozd 14.10.2011 13:09

Цитата:

Сообщение от Kolyaj
А fast-cgi это не то?

нет, не то.
там концепция в том, что отработавший процесс(обработавший 1 запрос) можно не убивать, а заставить обработать еще запросы.
При этом в каждый момент времени процесс думает только о нуждах одного запроса, и не начинает думать о новом запросе, пока не закончит старый.
Короче, это просто расширение CGI, позволяющее сэкономить на создании нового процесса, и все.

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

Цитата:

Сообщение от Kolyaj
Если нет, то какое-то другое решение есть, но вроде PHP там безбожно течёт, т.к. не приспособлен под такое.

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

Kolyaj 14.10.2011 14:46

Цитата:

Сообщение от Gvozd
Но, я не знаю о каком решении вы говорите, и если вы не вспомните название, то обсудить точно не получится.

Не, я всё-таки думал о fast-cgi. Понял, что не то.

Андрей Параничев 14.10.2011 18:03

Я импользую mongodb, но у меня не будет увеличения объема данных, а самые оперируемые данные кешируются в memcached.

x-yuri 15.10.2011 00:15

Цитата:

Сообщение от vflash
x-yuri, когда речь о MongoBD так всегда и говорят. не та задача и не так готовите.

а ты можешь предложить альтернативу? Или думаешь, что эта идея вообще тупиковая? Я вот про CouchDB думаю...

vflash 15.10.2011 00:50

CouchDB не знаю не пробовал. Они же мутят что-та новое, отсюда непонятно будут ли развивать CouchDB.

Андрей Параничев 15.10.2011 03:28

CouchDB хуже, чем MongoDB почти во всем.

Цитата:

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

x-yuri 16.10.2011 14:17

Цитата:

Сообщение от vflash
Они же мутят что-та новое, отсюда непонятно будут ли развивать CouchDB.

откуда такая информация?

Цитата:

Сообщение от Андрей Параничев
CouchDB хуже, чем MongoDB почти во всем.

скажем так, человек который использует couchdb (насчет mongodb не знаю), говорит, что:
Цитата:

Couch: Fail resist. Mongo: speed
но mongodb проще при переходе с реляционных БД

x-yuri 03.11.2011 17:37

наткнулся сегодня
Episode 1 - Mongo DB Is Web Scale


Часовой пояс GMT +3, время: 14:04.