Pull to refresh

Comments 120

Не совсем понял +1:
Эта операция должна проводится через транзакцию — если комментарий не будет сохранен, то он не должен попасть в профиль пользователю и в статью, эта операция само по себе должно выполнятся в серии. Другое дело, что если использовать, что-то с map/reduce, то тогда эти 4 операции превратятся в 1 (сохранение комментария), а все остальное через map/reduce делается.

Про утечки памяти хотелось бы побольше.
Частично согласен. Транзакцией можно пользоваться, когда участок когда не очень критичен к производительности. Если же мы говорим об операции, которая выполняется очень часто многими пользователями и затрагивает несколько таблиц, при использовании транзакций всплывут тормоза и дедлоки. В таком выполнение запросов параллельно является техникой оптимизации. У нас же всегда остаётся возможность откатить действия, если один из запросов сработал с ошибкой, но такая ситуация будет возникать пренебрежимо реже штатной работы.
Я бы их все же серийно выполнял — если один провалился нет смысла выполнять остальные и проще отлеживать, а так лишнии строки кода.
Провал это очень редкая ситуация, которой, теоретически, вообще быть не должно. Нет смысла опасаясь её уменьшать скорость работы, учитывая то, что возможность отката всегда остаётся.
Теоретически быть не должно, а практически бывает. И дальше — кропотливая и ужасная борьба с образовавшейся неконсистентностью. Так что транзакция. Тем более, что всё-таки запись в БД делается гораздо реже, чем чтение, и вот такие «оптимизации» очень сомнительны — лучше бы выборку кэшировали.
Абстрагируйтесь от комментариев. Я привел их ради простого примера распараллеливания задачи. Это может быть что угодно и акцент тут стоит, как раз, на очень частых операциях, которые транзакция погубит.
Ну насчёт чтения тоже есть пунктик — выведенные данные в редких случаях будут неконсистентными. Но на самом деле, на моей памяти как раз чтение данных обычно укладывается один запрос. Запись тоже должна была бы укладываться в один запрос, но мешает денормализация. А денормализация потому и делается, чтобы можно было данные в один запрос получить. Ведь чтение производится гораздо чаще.
UFO just landed and posted this here
А кто-то бы даже написал триггер, бррр…
Сильно скучно. Map/reduce наше все.
Расскажите, пожалуйста, подробнее про cloud9ide. Вы ее как-то настроили, чтобы она при тестовых запусках располагала исходники на вашем сервере?
Да, она ставиться очень просто:
1. Ставим node.js;
2. Клонируем репозиторий git clone github.com/ajaxorg/cloud9.git;
3. В директории bin запускаем cloud9.sh, во время первого запуска он выкачает зависимости и настроит себя;
4. По умолчанию он запускается на 127.0.0.1 на порту 3000
5. Чтобы указать путь к исходникам и другой интерфейс используем параметры.

Я запускаю его вот таким скриптом:
#!/bin/bash
/home/cloud9/bin/cloud9.sh -l 0.0.0.0 -w /home/workspace > /dev/null 2> /dev/null &

-1
Первое, с чем придётся столкнуться при разработке на Node.JS — это отсутствие полноценной IDE,

Может я что-то упустил, но у меня отлично работает WebStorm 3.0. Поддержка node.js из коробки (включая отладку).
Спасибо, за информацию. Обязательно попробую. Она вышла совсем недавно?
Где-то в районе начала декабря прошлого года.
Какие фреймворки, какие IDE, вы вообще о чём?

Node.js сам по себе — мощный фреймворк, в нём поднять html-сервер — дело 3 строчек.
Нет IDE? Это что, тоже серьёзно? JavaScript язык популярный, вряд ли найдётся _не подходящая_ среда разработки!

Простите за занудство, но статья ни о чём.
Какие утечки памяти-то? Потеряли var? А если, допустим, «потерять» объявлегние функции? Тоже язык (или фреймворк) виноваты?

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

http-сервер это далеко не всё, что нужно для полноценного проекта. Шаблонизатор, роутер, конекторы к БД, это тоже 3 строчки? К тому же, я написал, что в конечном итоге отказался от фреймворка в принципе и использовал модуля напрямую.

Утечки памяти? var далеко не самое страшное. Все переменные в области видимости замыкания не будут удалены сборщиком мусора, пока в на них останутся ссылки внутри замыкания. Достаточно запустить setInterval или навесить обработчик события и забыть их убрать, когда они перестанут быть актуальными, и они начнут засасывать в себя всю свою область видимости. А что если это происходит при каждом запросе?
Ну вот, как я и ожидал, навесили пару минусов.

Если для нормального контроля за кодом вам необходима какая-то специальная IDE (уникальная или почти уникальная под каждый фреймворк) — подумайте, стоит ли вам писать код вообще.

Так в чём проблема? Нужен шаблонизатор — возьмите шаблонизатор. Нужны коннекторы? Возьмите один для каждого типа БД, который вы используете.

Зачем поднимать монструозную штуковину, которая будет тратить неизвестное количество памяти, в которой есть неизвестные баги и которая от вас не зависит, а зависит от какого-то стороннего разработчика?

Да, я видел что отказались. Но сама фраза «Я начал со знакомства с WEB-фреймворками для этой платформы» очень показательна.
Я пишу проекты на Node.js и категорически утверждаю, что там не нужны какие-то глобальные фреймворки!
Единственный вариант — когда вы делаете универсальный движок для разных типов сайтов, который будет использоваться не вами. Т.е., когда вы сами пишете собственный фреймворк для ленивых.

Ну а про проблемы «забыл их убрать», «забыл написать», «забыл точку с запятой» я промолчу.
Я уже пережил состояние «я такой крутой, что пишу всё прямо в консоли и помню расположение всех методов своей программы построчно». Если для Вас, желание удобства при разработки для уменьшения её общего времени является критерием качества написания кода — это Ваше дело.

А проблемы и нет. Я так и сделал.

Через написание своей монструозной штуковины прошли все разработчики, а кто говорит что не прошёл — прошли, как минимум, 2 раза или занимаются этим прямо сейчас.

Да, фраза «Я начал со знакомства с WEB-фреймворками для этой платформы» довольно показательна. Она показывает, что я начал рассмотрение построения WEB-приложений для этой платформы с инструментов для этого предназначенных.
А я ведь совсем о другом писал.
Никакой «крутости», которую вы где-то увидели, никакого написания всего и вся в блокноте, конечно же. Просто говорить о том, что для Node.js нужен какая-то специальная среда разработки — это, как минимум, значит признавать своё невежество. Node.js — это фреймворк. «Среда разработки» (а по факту — подсветка синтаксиса и подсказки стандартных методов) нужна для Javascript, и их полным полно.

Написание — это совсем другой вопрос. Я говорил про использование таких штуковин. Необходимо понимать, что и для чего ты используешь. Хотя, предположу, что многие здесь подключат на сайт jQuery лишь для того, чтобы навешивать класс на какой-нибудь элемент.

WEB-фреймворк == инструмент для построения WEB-приложений??? Мы, кажется, в совсем разных мирах живём… Node.js — да, инструмент. Фреймворк на основе Node.js — это уже web-приложение. Брать одно приложение как основу для построения чего-то другого — бессмысленно, и, более того, вредно для поддержки, для производительности, для всего остального, кроме лени разработчика.
Странные вещи Вы говорите, которые вроде как и не противоречат, тому что я пишу, а спор выходит. Разве это плохо, если я хочу чтобы API Node.JS автокомплитилось у меня в коде? Или чтобы я мог перезапустить приложение после внесения изменения хоткеем из IDE? Пока нет — ну ладно живём, но когда будет — я буду этим пользоваться с удовольствием, т.к. это упростит процесс разработки.

Я проверил эти штуковины на «деле», понял, что они мне не нужны, выпилил их, сделал выводы и поделился в этой статье процессом того как я к ним пришёл. Если Вы изучая новую технологию сразу же знаете, что нужно использовать, а что нет, на уровне аксиом — я за Вас очень рад. Опыт научил меня как хвалебным так и ругательным обзорам слепо не доверять.

Про фрейморки над терминологией спорить бесполезно. Также можно сказать что и симфони/yui/kohana это веб-приложение для PHP. Не суть.
Смысл в том, что _начинать_ изучение чего-либо с фреймворка — очень-очень вредное дело. Представьте, что будет, если любого будущего JavaScript-разработчика начинать обучать с jQuery?
Впрочем, тут и представлять не надо, сейчас большинство таких…
Я же не Node.JS начал изучать с фреймворка. На Node.JS я пишу ещё с версии 0.2, но до этого использовал его только для разработки comet-приложений и т.п. вспомогательных сервисов. А потом мне стало интересно попробовать именно разработку полноценного web-сайта, соответственно я пошёл смотреть на то, что разработано в этом направлении.
Тогда я в шоке^2, а не просто в шоке.
>Ну а про проблемы «забыл их убрать», «забыл написать», «забыл точку с запятой» я промолчу.
Ну зачем же молчать, это вам может быть всё очевидно если вы в жаваскрипт пришли из более зрелых языков, где в каждой книжке расписаны best-practices по работе с ресурсами итп. А для миллионов жаваскриптеров без достаточного образования всё может быть не таким очевидным, тк им просто даже негде об этом читать. Повсюду лишь всякая бредятина про асинхронность жаваскрипта и прочая муть, а нормальной информации по разработке масштабируемых(в плане разработки) и надёжных приложений нет. И это проблема жаваскрипта, тк язык должен оцениваться не чисто как яп, а то какое в нём сообщество, книги/образование итд.
Вы ошиблись, кроме JS я почти ничего не знаю, если не считать разных небольших обрывков других языков. Хотя пытаюсь этот свой недостаток исправить.

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

Если я пишу свой универсальный движок для своих сайтов? Это можно? Или каждый свой сайт с нуля разрабатывать? А если можно, то выложить его в паблик можно? А если начал писать и увидел, что это уже есть в паблике, то всё равно продолжать писать свой??

В какой-то мере, да, издеваюсь, показывая, что процитированная фраза слишком категорична, чтобы быть руководством к действию во всех случаях.
Какие утечки памяти-то? Потеряли var? А если, допустим, «потерять» объявлегние функции? Тоже язык (или фреймворк) виноваты?

А кто же тогда виноват? Программист? Нет, человеку свойственно ошибаться, так что человек тут не может быть виноват. Виноват несовершенный инструмент, который позволяет человеку ошибаться. Ведь человеку для того инструменты и нужны, чтобы преодолевать собственное несовершенство, в том числе и ошибаться. Вот есть инструменты, где потерять var или объявление функции не получится. Точнее, получится, но инструмент такую «программу» даже запустить не даст.
Поругайте тогда JavaScript за то, что там, если не ставить в конце строк точку с запятой, могут возникать проблемы.
Или за то, что если вызвать несуществующую функцию, то вылезет ошибка.
Человеку ведь свойственно ошибаться, да?

А программисту должно быть свойственно думать перед и во время написания кода и проверять код во время и после написания.
Поругайте тогда JavaScript за то, что там, если не ставить в конце строк точку с запятой, могут возникать проблемы.

А не возникнет там ошибка. Правила автоматической подстановки точек с запятой вполне строго определены.
Или за то, что если вызвать несуществующую функцию, то вылезет ошибка.

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

Проверять кто будет? Опять же, несовершенный человек, которому свойственно — читай выше. Программист тут виноват в том, что не написал юнит-тестов. Или кто-то неправильно организовал работу этого программиста. Или кто-то выбрал javascript там, где его не следовало выбирать.
А если сминифицировать код — то может и возникнуть. Или если забыть эти самые правила автоматической подстановки.

Сюрприз-сюрприз — javascript интерпретируемый язык! Он не компилируется.

В вашем примере виноват кто-то другой в том, что считает человека, за которого выбирают на чём ему программировать, программистом.
А если сминифицировать код — то может и возникнуть.

Это проблема кривых минификаторов.
Или если забыть эти самые правила автоматической подстановки.

А можно вообще забыть синтаксис языка, и чо?
Сюрприз-сюрприз — javascript интерпретируемый язык! Он не компилируется.

Я так скажу — сейчас понять, что считать компилируемым языком, а что интерпретируемым — очень и очень сложно. Скорее, речь больше о том, есть ли такая штука, как запуск прямо из исходников «из коробки» и насколько это принято в сообществе. В принципе, мне никто не мешает за полчасика для Java наваять подобный launcher, который будет прямо исходники запускать.
В вашем примере виноват кто-то другой в том, что считает человека, за которого выбирают на чём ему программировать, программистом.

Ой, ну хватит уже этого толстого троллинга. Говнокодер — это не тот, кто допускает ошибки по невнимательности, это тот, кто организует свою деятельность так, чтобы допускать как можно больше ошибок. В этом смысле тот, кто пишет проект, больший трёх строчек, без IDE — и есть натуральный говнокодер, ибо IDE способствует снижению количества ошибок на квадратный метр кода. Ну ещё можно говнокодером считать того, кто на JS пишет банковскую систему или там систему управления спутником.
Я о том и говорю, что язык тут не при чём. Если человек не умеет писать код — то он на чём угодно ошибок наделает, даже если будет знать синтаксис, пунктуацию и грамматику. И никакая IDE ему не поможет.
Ой, ну не надо меня тут за нос водить. Смысл изначального поста в том, что IDE не нужен как класс, а не в том, что говнокодеру IDE не поможет.
Смысл моего начального комментария — не нужна какая-то специальная IDE именно для Node.js, а подойдёт любая, которая подходит для JavaScript вообще.
UFO just landed and posted this here
Тут не в типах дело. Я, скажем так, не за статическую типизацию (и не надо только путать разрез статическая/динамическая с разрезом строгая/нестрогая). Я за то, чтобы отлавливать ошибки как можно раньше. Для Java это не только система типов, это ещё определённые соглашения, это хинты в IDE, это всяческие соглашения, это анализаторы кода вроде findbugs, это юнит-тесты и т.п. Оно всё панацеей не является, но всё-таки сильно снижает шансы ошибиться на ровном месте. Статическая типизация ещё помогает быстрее набирать код, хотя вон javascript-гуру утверждают, что если использовать систему документирования кода, то IDE может прямо из комментариев выцеплять информацию о типах. Получается, правда, та же самая статическая типизация, только опциональная (привет dart), и не дающая преимуществ в рантайме. Да, статическая типизация требует определённых накладных расходов уже от самого программиста. Причём, программистом может быть как человек, пишущий прикладной код, так и тот, кто пишет компилятор и, соответственно, осиливает или не осиливает вывод типов.
Для меня разница между динамической типизацией и статической лишь в том насколько удобно контролировать типы когда нужно и не контролировать когда не нужно. Но как-то получается, что, несмотря на то, что контролировать типы приходится часто, те редкие случаи когда их контролировать не нужно в языках со статической типизацией выливается в большие проблемы, в то время как контроль типов в динамических хоть и засоряет временами код, но зато прост как кирпич.
Это зависит от языка. Java и C# официально статически типизированы, но они информацию о типе хранят с самим объектом в рантайме, так что никто не мешает всё привести к object'у и дёргать методы через reflection. В C# вон вообще для этого на уровне языка сделали конструкцию. В этом смысле Java и C#, вообще-то, вполне себе динамически типизированные, но со статической оценкой типа сверху.

А можно пример ситуаций, где статическая типизация выливается в большие проблемы?
Это скорее костыль, типа как в PHP контролировать тип параметра через is_int().

Работа с множеством объектов без общего предка без использования рефлексии (её использование я уже считаю большими проблемами, даже в динамических языках). Задача типа «принять множество произвольных объектов, вызвать те из них, у которых есть метод run».

P.S. Ориентируюсь больше на C++ 2.0, чем на последние версии C# и Java — на них ничего сложного писать не доводилось, как и на последних версиях С++. Сейчас вспоминаю для сдачи экзамена по второму изданию (1991) «Язык программирования C++» Страуструпа.
>вызвать те из них, у которых есть метод run

>без использования рефлексии

Reflection
Это скорее костыль, типа как в PHP контролировать тип параметра через is_int().

Ничуть
Работа с множеством объектов без общего предка без использования рефлексии

В Java такой проблемы нет — java.lang.Object и обёртки для примитивных типов. В C# — тем более — System.Object, без всяких обёрток. И да, нафига вообще объекты без общего предка в общей коллекции хранить? Неправильный дизайн?
её использование я уже считаю большими проблемами, даже в динамических языках

«Статическая типизация костылявая потому что она костылявая». Всё же хотелось бы услышать, чем не угодила рефлексия.
Задача типа «принять множество произвольных объектов, вызвать те из них, у которых есть метод run».

Задача поставлена неверно. В постановке задачи уже есть намёк на то, что решаться она должна с помощью динамической типизации. В общем, не любят статику те, кто просто не умеет её готовить.
В Java такой проблемы нет ... . В C# — тем более...

Как это сделать в C++?

Всё же хотелось бы услышать, чем не угодила рефлексия.

Многословностью.

В общем, не любят статику те, кто просто не умеет её готовить.

Лет 20-15 я достаточно пописал на статических языках (в основном C++, чуть-чуть на первом Java), потом писал на динамических. Думаю могу их сравнивать, пускай и субъективно и не самые актуальные версии рассматриваю, но и мнение свое никому не навязываю.
>В постановке задачи уже есть намёк на то, что решаться она должна с помощью динамической типизации
В постановке задачи написано что она должна решаться с помощью рефлексии
Вот за что я так не люблю разработку на Javascript так это из-за «Да-да, в одном труднодоступном месте я допустил опечатку в имени переменной, что и послужило причиной падения.» В Java скорее всего это бы разрулилось ещё на этапе компиляции

А вот плюсов по сравнению с Java как-то маловато нашел в Вашей статье…
Кстати, ни слова про кофе? Я бы двинулся если бы все, что написал, писал на javascript.
JavaScript вполне самодостаточный, красивый и удобный язык. Есть жизнь и без кофе.
Посмотрите в сторону PlayFramework на Java (http://www.playframework.org/). Там вам и пересборка приложения при изменении файла (прям как в ПХП) и асинхронное программирование и много всего ещё.
Плюсы по сравнению с Java я выделял: быстрее скорость перезапуска приложения, гораздо меньше исходного кода, больше возможностей сделать шаг влево, шаг вправо при необходимости. Java это всё же enterprise язык. После разработки проекта на Java + Spring + Hibernate я больше в веб-приложениях использовать его не буду.
Ещё раз говорю посмотрите на PlayFramework )
А вот вы привели пример с добавлением комментария. Обычно при добавлении комментария страница идет обновление страницы, чтобы пользователь мог увидеть что он действительно добавил комментарий. А как в случае с асинхронностью?
Мы ожидаем выполнения тех действий которые нам необходимы, чтобы отобразить пользователю необходимую информацию. Когда все эти действия будут выполнены мы получим от них callback'и можем смело рендерить страницу. Для жонглирования несколькими асинхронными вызовами есть очень удобный модуль async.
На вашем месте я бы обозначил еще одну проблему, которая для некоторых приложений может стать критической. Node.JS выполняет код асинхронно в одном процессе и одном потоке, несмотря на то, что сама event-машина работает асинхронно, ваш код, который отвечает на события не обладает этим свойством и асинхронность достигается только за счет асинхронных вызовов с установлением коллбека. Конечно, это не всегда минус, но и не всегда плюс. Я прекрасно понимаю, что это by design, а не ошибка. Но на это нужно обращать пристальное внимание, когда вы выбираете технологию для разработки, поскольку в больших приложениях вам придется мыслить «процессами», а встроенная возможность запускать дочерние процессы и разделять использование порта между процессами не решает многих проблем, например проблем с comet-серверами на основе сессий, а не каналов. И некоторых других (когда данные обрабатываются в памяти, а не записываются в БД).

Если ваше приложение использует не только логику запроса-ответа, как интерфейс к базе данных, а содержит какую-либо бизнес-логику на JavaScript, то для повышения быстродействия вам придется продумывать горизонтальное расширение заранее, либо вычленять отдельные участки кода и запускать в отдельных процессах, взаимодействия с ними с помощью систем очередей, или по паттерну publisher/subscriber. Или, как минимум, следовать логике встроенного раздельного использования порта в веб-сервере, а более сложную логику всю перенести в отдельный сервис, запускающийся в своем процессе.

Еще одним минусом я считаю низкое качество и количество библиотек. Это, конечно, временно, но в некоторые даже часто используемые библиотеки мне приходилось отсылать коммиты, исправляющие довольно простые и очевидные неточности, которые приводили к проблемам, в т.ч. с утечками памяти.
Полностью согласен с Вашим комментарием. Часть этих вещей я описал в статье, немного другими словами. Немного добавлю про comet-приложения. Да, разделение порта между процессами создаёт некоторые трудности, когда пользователей нужно делить не по каналам. Но у нас остаётся возможность общения форкнутых процессов с родителем и наоборот. Ну и второй момент — практически всегда можно найти критерий по которому пользователей можно разделить на «мнимые» каналы. Например это может быть геолокация, используемый язык и т.д., зависит от приложения.

Про сложные вычисления я тоже упоминал. Такие задачи следует выностить за пределы event loop или использовать другой, более подходящий язык. Но в большинстве web-проектов нет такой бизнес-логики, которая бы серьёзно затормозила event-loop настолько, чтобы это было заметно. А для частых задач, типа ресайза изображений уже есть модули, которые будут выполнять эту работу асинхронно, не тормозя event loop.

Библиотек много, качественные не все, но развитие идёт. Это нормально для молодой платформы. Всё будет.
Вычисления не обязательно должны быть сложными, они вообще не обязательно должны быть «вычислениями», если вы понимаете, о чем я. Это могут быть любые операции, которые выполняются довольно часто, либо постоянно. Держать их в одном процессе вместе с веб-сервером будет накладно, а в некоторых случаях — невозможно.
>Несмотря на то, что в JavaScript тоже есть конструкция try-catch, нам она не поможет, т.к. большая часть кода работает асинхронно (операции ввода/вывода).
Может всё же проблема не в том что всё работает асинхронно?
В нормальных языках можно делать так:

@async
def home_page():
    a = db_query("one")
    b = db_query("two")
    try:
        yield await(a, b)
    except:
        raise InternalError()
    render("home.html", a, b)


>Самым значимым преимуществом Node.JS я считаю асинхронный ввод/вывод и прозрачность работы с ним.
В Python, C/C++(скоро в C++ будет ещё удобнее чем сейчас, автор C# async/await уже закинул proposal на добавление аналога в C++, хотя и сейчас с помощью макросов можно легко решать те же проблемы), Erlang, Haskell, C# итд нет никаких проблем по работе с асинхронным вводом/выводом. Джаваскрипт я бы в этот список ни за что не добавил, тк в нём неудобно работать с асинхронным вводом/выводом.
Приведённая Вами конструкция форкает процесс? Или как она работает?
создаёт две подзадачи db_query, приостанавливает работу текущей задачи yield (python generators) дожидаясь выполнения двух db_query.
Это понятно. Я про то, где работают эти 2 подзадачи? И может ли при этом основной процесс работать дальше (пока ждёт их)? Принимать соединения и т.п.
Зависит от планировщика. Достаточно легко сделать как в нод.жс, будут эти подзадачи запускаться внутри одного треда и не останавливать этот тред на i/o операциях.
Боюсь, что асинхронность в вашем примере это многопоточность, а не асинхронность, как в Node.JS.
Приостанавливать работу текущей «задачи» в Node.JS нельзя, поскольку общая задача выполняется синхронно в одном потоке, который ожидание результата (синхронное) просто остановит. Если не использовать фибру, например, или подобные пакеты.
боюсь что это обычная concurrency.
Это один из вариантов корутин на Python.
Конструкция не форкает процесс а, говоря языком NodeJS, разбивает функцию home_page в месте где стоит yield на 2 функции с общими переменными, первая отработает сразу а вторая будет возвращена как коллбек.
UFO just landed and posted this here
JavaScript это нормальный язык, не менее нормальный, чем Python, который кстати на него довольно похож, например динамической моделью ООП. А описанное вами возможно только в случае, если асинхронный поток можно «слайсить» (я не знаю, какой тут термин подойдет) с помощью node-fibers, например. В tornado такой функционал является встроенным, хотя сам по себе не является частью «стандартного» асинхронного IO.
>А описанное вами возможно только в случае, если асинхронный поток можно «слайсить» (я не знаю, какой тут термин подойдет) с помощью node-fibers, например.
node-fibers использует libcoro, а это достаточно неэффективный способ при условии если у нас будут сотни тысяч таких корутин.

>В tornado такой функционал является встроенным
торнадо не оч удачный пример для того чтобы демонстрировать возможности питона :)
ой, спутал торнадо с твистед… Торнадо, да, хорош :)
А вот мне всегда было интересно как используют yield для асинхронных вызовов. А если нужно делать ассинхронный вызов в генераторе, который используется в цикле?
например:

for page in home_pages():


а home_pages — генератор + ассинхронные вызовы.
немного не понял вопрос.
В моём примере декоратор выполняет роль создания задачи и добавление её в текущий планировщик (что-то вроде async'ов в C#).
Не знаком с вашим фреймворком, но попробую набросать идею:
def pages():
    a = db_query()    
    res = yield await(a)      # тут мы по-идее должны вылететь аж до реактора
    for row in res.rows
        yield row['name']     # а это генератор для цикла

for page in pages():
    print page


как разруливается этот конфликт, когда yield используется и для генератора, и чтобы прервать контекст и продолжить, когда данные будут готовы?
@async
def query():
    a = db_query()
    res = yield await(a)
    return res

def pages(res):
    for row in res.rows:
        yield row['name']

@async
def xxx():
    x = query()
    yield await(x)
    for page in pages(x.result):
        print page
Я понял, выход — вынести yield await из генератора. (если это возможно)
Для любителей языка Haxe, есть либа HaxeNode.
Т.е. испульзуя ее, мы получаем статическую проверку типов, классы и т.д.
Разрабатывал несколько REST-сервисов на Node.js. Были серьезные проблемы с утечками памяти при работе с XML. После долгих наблюдений (процесс node отъедал всю память сервера за 12 часов), выяснилось что проблема в модуле работы с XML.
Я использовал libxmljs главным образом потому что он написан на C++, имеет хорошую производительность по сравнению с нативными (Javascript) модулями и позволяет как создавать, так и разбирать XML.
После этого для парсинга XML выбрал node-expat (тоже C++ модуль), а для создания xmlbuilder (нативный Javascript модуль). Уже месяц полет нормальный.
Так, автор, жду от вас конфигурацию сервера, графики посещения и потребления ресурсов после хабраэффекта, в следующей статье.
Статья будет через несколько дней. Постараюсь подробнее описать техническую часть.
1. У меня возникли проблемы с производительностью в зависимости от аптайма скрипта. Не могли бы вы мельком глянуть сюда (QA)?
2. Почему вы вернулись на Netbeans? Ввиду слабой её поддержки javascript-а я наоборот ищу замену. Единожды попробовав webstorm, я сделал вывод что поддержка может быть в десятки раз лучшей. Но к самому webstorm-у как к IDE привыкнуть за trial не смог :(
3. Что вы думаете о node-sync? На мой взгляд он решает 99% проблем простых nodeJS приложений, не нарушая при этом event-loop идеологию.
>Что вы думаете о node-sync?
node-sync использует node-fibers, те в свою очередь используют libcoro, а эта либа реализует примитивные user space thread'ы, в которых та же самая проблема как и с ОС тредами — это выделение большого куска памяти под стэк.
Не могли бы немного подробнее осветить этот вопрос? Проблема только в потреблении памяти? Вываливается ли это в проблемы производительности (при условии наличия своб.памяти)? По какому принципу работает space thread? Это настоящие потоки или их имитация? Полагаю, это многим будет интересно. Насколько я понял yield-ам нашли применения во многих совр.языках.
>Проблема только в потреблении памяти?
Это как бы и была основная проблема :)

>Это настоящие потоки или их имитация?
Смотря что понимать под настоящими потоками. По мне так они все настоящие :)

>Насколько я понял yield-ам нашли применения во многих совр.языках.
Ну тут не то чтобы совр.языки, это всё нодовцы, они выдают за инновации то с чем люди уже работают не одно десятилетие, причём довольно успешно, в отличае от нодовцев :)
Из новинок стоит посмотреть только на Split Stacks
Erlang процессы вроде жрут 192 байта при старте и отъедают по мере необходимости
В Хаскелле ещё меньше
Есть stackless python, но по своему опыту могу сказать что достаточно и простых генераторов для вебразработки в питоне.
В C#5.0 есть async/await (в C++ уже есть proposal на добавление такой же фичи, а пока работают с чем-то вроде protothreads)
итд итд…
Там тоже самое что и в node-fiber(libcoro), приходится сразу выделять по максимуму памяти для стэка.
Например в федоре 16(64бит) по дефолту 8мб для nptl тредов. И тут встаёт проблема сколько же выделять для user space тредов. Выделишь мало — получишь крах системы, выделишь много — получишь сильный оверхед.

$ ulimit -s
8192
при таком раскладе, как я понимаю, единственное преимущество перед ОС-тредами в «отсутствии» race-conditions?
withdraw() {
money = this->get_money();
result = yield db_query();
money -= result;
this->set_money(money)
}

Тупой конечно пример, но надеюсь покажет что проблема с синхронизацией остаётся, тк можно одновременно запустить два withdraw. Да, они не будут выполняться параллельно(если крутить всё в одном ОС треде), но они оба запустятся, остановятся на db_query, а потом кто-то из них перезапишет результаты другого(set_money).
ну я потому и поставил «отсутствие» в кавычки) Ок, ясно.
1. Попробуйте нагрузить своё приложение огромным количеством запросов т.к. время работы скорее тут играет меньшую роль, чем объём выполненной приложением работы. Для этого подойдут утилиты ab или siege. При этом мониторьте использование памяти (есть удобный модуль connect-profiler ну или хотя бы просто через htop), чтобы понять течет ли она. На работе мы используем node.js для довольно нагруженного сетевого демона и он неделями работает нормально не кушая лишнюю память, хотя некоторые проблемы были до версии node 0.6.8 (кажется).
2. К NetBeans просто привык, т.к. большую часть кода (PHP) пишу именно в нём.
3. node-sync выглядит вкусно и на первый взгляд решает проблему с возвратом ошибки. Но, как уже написали выше, использует thread'ы, со всеми вытекающими. К сожалению я пока не использовал эту библиотеку и поэтому не смогу её как-то прокомментировать. Очень интересно было бы сравнить быстродействие и потребление памяти в реальном приложении, с реальными нагрузками с использованием этой библиотеки и без неё.
Привык использовать TDD. Вы пробовали? Если да — не забудьте осветить это в следующей части.
Я долго смеялся, увидев сравнение производительности Java и Node.JS. ...

Во-первых, вы подменяете понятия. Я не сравниваю Java и Node.JS. Я сравниваю Netty и Node.JS.

Во-вторых, упоминание Spring и Hibernate, здесь абсолютное неуместно.

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

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

>Я сравниваю Netty и Node.JS.
… для разработки hello world веб сервера и обслуживании 100 одновременных соединений.
И зачем говорить то на каком железе всё крутится, ведь это так неважно. Netty то у нас умный в tp крутится, а нод должен одним процессом всё обрабатывать.

>Во-третьих…
вам это пригодится Type system, не проходите мимо :)
Представьте себе, я и есть автор статьи.

Netty то у нас умный в tp крутится, а нод должен одним процессом всё обрабатывать.

Железо: 4 ядерный феном с 8 Гб мозгов. Насчёт трэдпулов, хороший аргумент, но с другой стороны нетти крутить проще, чем отдельную подсистему Node+Nginx. Так что тут ничья.

вам это пригодится Type system, не проходите мимо :)

Обоснуйте, пожалуйста.
>Представьте себе, я и есть автор статьи.
Да я понял что вы автор статьи на том блоге, я про автора этой статьи на хабре :)

>Обоснуйте, пожалуйста.
weak/stong typing != static/dynamic
Например в Си static weak typing type system
>Что не так с моим утверждением выше?
«потому как этот код не может быть проверен до того, как будет выполнен.»
«The process of verifying and enforcing the constraints of types – type checking – may occur either at compile-time (a static check) or run-time (a dynamic check)»
Вы придираетесь. Что ж, JavaScript не проверятся вовсе :)
Я считаю количество кода, особенно когда оно так различается, очень серьёзным аргументом. Можно долго говорить о различии в языках и в их предназначении. Но не нужно забывать, что приложение идёт в бой не одно, а в инфраструктуре. Кеширование и другие тхники оптимизации нивелируют нагрузку на само приложение. Обращаю Ваше внимание, что я не сравниваю зыки по скорости, я вполне допускаю, что Netty может реально выиграть эти 40% на hello world. Но в продакшн пойдёт не hello world, а готовая инфраструктура. Там будет не 1 поток node.js и перед ним, в большинстве случаев, будет стоять nginx. Для многих запросов, дёргать бекэнд node.js вообще будет не нужно. На такой инфраструктуре, даже если какой-то выигрыш у Netty останется, в чём я очень сильно сомневаюсь, мы получаем приложение с гораздо меньшим объёмом кода, который поддерживать дешевле (в человекочасах), а на сэкономленные деньги мы можем позволить себе, при необходимости, купить ещё один сервер (при этом продолжая экономить человекочасы на поддержку и развитие кода). Так-же обращаю Ваше внимание на то, что сейчас мы говорим о web-приложениях (будь то блоги, сервисы или браузерные игры). В данном контексте, чтобы сервер (я говорю о нормальном выделенном сервере) реально не справлялся с нагрузкой, нужно иметь посещаемость порядка 100к уникальных человек в сутки. В этом случае время на поддержку и развитие кода становится ещё дороже чем новая железка. Такая посещаемость у любого проекта будет далеко не сразу (если Вы не Google). А для быстрого старта гораздо важнее меньший объём кода, чем его сомнительный выигрыш в производительности, т.к. когда посетителей не много, оно будет быстро работать как на node.js так и на Java и на PHP и на всём остальном.
Вы меня не поняли: больше кода=дороже. Для PHP и JavaScript согласен, для Java нет.
Аргументируйте? C Вашей точкой зрения я вряд ли соглашусь, т.к. есть опыт разработки web-проекта на Java и поддерживать его гораздо сложнее чем проекты на PHP и JavaScript. Так же у меня нет цели кого-то убедить. Я высказал свою точку зрения и привёл довольно весомые, я считаю, аргументы в её поддержку. Соглашаться с ними или нет — дело каждого. Если хотя бы кому-то это поможет сделать правильный выбор — я уже не зря потратил время.
>есть опыт разработки web-проекта на Java и поддерживать его гораздо сложнее чем проекты на PHP и JavaScript

Может это, потому что вы просто не умеете их готовить?
Чего Вы хотите достичь этим вопросом? Показать свою крутость в Java-программировании? Отлично. Я не увидел весомых аргументов с Вашей стороны показывающих привлекательность разработки web-приложений на Java. Если кроме провокационных вопросов, Вам добавить нечего — дальнейшую дискуссию считаю бессмысленной, т.к. это будет холивар.
Вы тоже не указали весомых аргументов против кроме того, что вам не нравиться
Прочитал, тезисы:
Java — много букв, Nodejs — мало букв.

Nodejs — круто.

При этом никто не подумал о том, что Netty:
а) Не требует оверхэда на TCP-транспорт для балансировки
б) Не требует инсталляции, деливери и деплоймента отдельного приложения(Nginx) для утилизации доступных ресурсов
Тестирование проходило на 4х ядерном процессоре. Следовательно netty используя 4 (как минимум) потока получала преимущество. Вы пробовали запустить 4 node?

Если входить в крайности — node, с недавнего времени, тоже не требует дополнительный балансировщик. Есть cluster api, который позволяет нафоркать нужное количество процессов и распределять между ними запросы. Но по факту для web-приложений nginx подсказывает использовать здравый смысл. Сложные слова типа «деливери» и «деплоймент» на деле выливаются в несколько команд в консоли и заливку конфига. Не вижу причин нагружаеть приложение тем, с чем лучше всего справляется nginx. Каждый должен заниматься своим делом.
Эти сложные слова НЕ означают пару команд.
Вы знаете: нынче nginx не рекомендуют разве что при поносе.
Что в этом плохого? Используем nginx на всех проектах — не было ни единого разрыва.
Звучит как серебряная пуля, поэтому я так скептичен.
>Но по факту для web-приложений nginx подсказывает использовать здравый смысл
Всё очень сильно зависит от задач, очень часто не нужна дополнительная прослойка в виде nginx'а, так что советую посмотреть ещё на lvs
Вы не ответили ни на один из моих вопросов, сами не привели ни одного аргумента. И либо не видите, либо не хотите видеть моих. А это называется троллинг. Извините, не кормлю.
Окей, последний вопрос. Вы на самом деле не видите никакого смысла в тех дополнительных строках кода, которые приходится писать, чтобы реализовать что-либо на Java?
Не для Web-приложений.
Гляньте на досуге www.stripesframework.org/, если не видели. Глоток свежего воздуха. Для меня по крайней мере.
Ну на самом деле количество строк кода, которые нужно будет написать для всевозможных тестов будет сопоставимо обычному жава коду. Вот только выхлопа от тестов будет меньше, тк в жаве эту доп инфу используют различные инструменты начиная от иде, заканчивая всякими анализаторами.
Но я всё равно не стал бы использовать жаву для разработки вебприложений, тк там до сих пор нет решений для легковесной concurrency.
А чего вы пытаетесь достичь сравнивая количество строк кода?
Спасибо за статью, понял две вещи — NodeJS по сути почти то же самое, что и phpDaemon; и то, что вскоре я столкнусь с теми же самыми проблемами, когда буду писать свой фреймворк и тестовый сайт на phpd. Статья интересная, затронуто много моментов, касающихся «неумирающей» серверной части, мне это пригодится.
Sign up to leave a comment.

Articles

Change theme settings