Пользователь
0,0
рейтинг
13 февраля 2012 в 11:13

Разработка → Разработка WEB-проекта на Node.JS: Часть 1

Прошла неделя с момента пиара на хабре моего проекта «Что делать?». Я напомню, что этот проект начинался, как эксперимент по разработке среднестатистического WEB-проекта целиком на JavaScript (Node.JS). Сейчас я хочу поделиться с сообществом результатами этого эксперимента, полученным полезным опытом, а также подробной картой с отмеченными на ней граблями.

Эпизод 1: начало пути


Я ставил перед собой следующие цели:
  • Понять, насколько удобно разрабатывать обычные WEB-проекты на Node.JS;
  • Сравнить скорость разработки на Node.JS с другими используемыми технологиями (в моём случае это были PHP и Java);
  • Добраться до подводных камней, с которыми не сталкиваешься на многочисленных синтетических примерах;
  • Оценить работу готового проекта: стабильность, устойчивость к нагрузкам, сложность поддержки и развития такого проекта.
Этот проект стал моим первым опытом разработки полноценного сайта на Node.JS, до этого я использовал его только для написания вспомогательных сервисов для рабочих проектов. Я начал со знакомства с WEB-фреймворками для этой платформы. На тот момент их существовало уже несколько и был выбор. На этом этапе нужно понимать, что если писать на JavaScript так же, как на PHP, или как на Java, или как на любом другом языке, это ни к чему хорошему не приведёт. На JavaScript нужно писать, как на JavaScript, иначе зачем он нам вообще (спасибо, Кэп)? Поэтому сразу проходим мимо тучи фреймворков, предлагающих различные реализации классического наследования, синхронного программирования и т.п. костылей, не свойственных языку. Я искал «тру»-JavaScript путь и хотел оценить именно его, а не порт PHP на JavaScript.

Из всех фреймворков выбор пал на Express. Он показался мне наименее перегруженным излишествами и при этом наиболее полно соответствовал моим требованиям и его можно было легко дополнить сторонними модулями.

От фреймворка я хотел следующего:
  • MVC архитектура;
  • Роутинг;
  • Работа с СУБД;
  • Шаблонизатор;
  • Поддержка мультиязычности;
  • Поддержка многопоточности;
  • Минимальный оверхед.
Также он должен был быть прост в понимании и представлять из себя удобный инструмент, а не ещё одну технологию, требующую дополнительного изучения.

Эпизод 2: путь самурая


Поигравшись немного с Express на тестовом примере, разобравшись в его архитектуре и изучив исходный код, я принял решение сделать свой фреймворк, который бы удовлетворял все мои потребности и не был перегружен лишним для меня функционалом. Велосипед — скажите Вы. Опыт — скажу я. Один из лучших способов понять систему — разработать её аналог самому. Фреймворк был разработан, отлажен, и на нём была основана первая версия сайта. Сайт был запущен, и я стал наблюдать за его работой, параллельно исправляя всплывающие ошибки и добавляя новые фичи.

Эпизод 3: великий потоп


Естественно, что первое время на сайте было крайне мало посетителей, чтобы хоть как-то объективно оценить его работу. Однако, через несколько дней, я обнаружил, что сайт лежит. Упал он молча, в логах не было ничего подозрительного, но падению сопутствовала серия быстро идущих друг за другом http-запросов — это был чей-то робот. Эти запросы никак нельзя было назвать нагрузкой, многие роботы сканируют сайты с такой скоростью, и падать из-за этого он никак не должен. Я поднял сайт и протестировал его через утилиту siege. И действительно — сайт ложился даже на совсем маленьком количестве параллельных запросов, что совершенно не соответствовало моим ожиданиям. Логи молчали. Печаль наростала. Начались раскопки.

Эпизод 4: первый камень


Повторяя эксперимент, я следил за тем, что происходит с сервером и обнаружил проблему — процесс node выжирал всю доступную память и либо вырубался, либо зависал (переставал принимать http-запросы). Оговорюсь, что во время разработки я старался следить за расходом памяти, т.к. это один из самых опасных моментов в долго работающих приложениях. Лишние замыкания не делал, var не терял, в общем вёл себя аккуратно. В очередной раз перебрав свой код, я убедился, что ошибка не в нём и, честно-говоря, огорчился, т.к. там было бы проще всего её исправить. Отладчик для Node.JS существует, он довольно удобный, но отлаживать Node.JS приложение сложнее из-за его асинхронной работы. Каюсь, я не достиг 80-го уровня в работе с этим замечательным инструментом и вычислить утечку не смог. Так закончился мой отпуск. Времени на познание силы Node.JS стало гораздо меньше, и я решил отложить это дело до лучших времён. Не удовлетворённый результатом, я написал маленькую утилитку, которая перезапускала процесс каждые сутки. На таких костылях сайт проработал 4-5 месяцев. Тем временем, развитие Node.JS не стояло на месте. Новые версии выходили одна за другой, да и сторонние модули тоже развивались, избавляясь от детских болезней.

Эпизод 5: новая надежда


И вот, после довольно долгого перерыва, в change log'е Node.JS появились записи об исправленных утечках памяти (версии 0.6.6 — 0.6.7). Так же, начиная с версии 0.6.0, в стабильный релиз попал cluster api, который позволял избавиться от лишних плясок для запуска нескольких процессов node. Всё это добавило энтузиазма и заставило посмотреть на проект под новым углом. К этому времени я уже видел, какие части моего фреймворка не используются, чего в нём не хватает, что не удобно. Плюс ко всему, я решил заменить MySQL (изначально использовался он) на MongoDB.

Ещё раз проанализировав популярные фреймворки, я понял, что все они, по большому счёту, представляют из себя сборки различных модулей и небольшие доработки “от себя”, а также диктуют свои правила построения приложения. Всё это загоняет в жёсткие рамки при сомнительном выигрыше. Если необходимо обновить отдельный модуль, а фреймворк с ним конфликтует, то придётся ждать, когда обновлённая версия будет добавлена в него разработчиками. Или если Вы хотите использовать модуль, который данный фреймворк не поддерживает, например, любимый шаблонизатор. Что делать? Форкать и добавлять поддержку, а потом вручную мёрджить обновления в ожидании, пока разработчики фреймворка примут ваш pull request? Нет!

Модульная система Node.JS вполне позволяет не использовать фреймворки (читать — готовые сборки модулей), а работать с модулями напрямую. При этом дополнительный функционал, вместо заворачивания в фреймворк, нужно выносить в отдельный модуль. Такой подход сильно увеличивает гибкость системы и улучшает повторное использование кода.

Так у меня появился план рефакторинга проекта. Он состоял из следующих пунктов:
  • Отказаться от использования фреймворка, перейти к прямому использованию модулей;
  • Выбрать из огромного количества модулей наиболее подходящие для решения моей задачи;
  • Заменить MySQL на MongoDB;
  • Для организации запуска нескольких процессов node использовать, теперь уже нативный, cluster api.
Ещё несколько выходных, и план был реализован. Всё прошло довольно гладко, количество кода уменьшилось, структура приложения стала более понятной. Всё было протестировано и готово к запуску. Тогда я опубликовал пиар-статью на хабре и стал ждать.

Эпизод 6: эпик вин


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

Выводы


Нельзя писать на JavaScript только ради JavaScript. Выбирать язык по причине того, что он крутой/новый/популярный (нужное подчеркнуть) — глупо. Нужно чётко понимать, чего мы хотим от технологии и что она может нам дать, а также что она попросит взамен. Моей главной задачей было выявить все эти “что” и получить ответ на вопрос: «подходит ли Node.JS для разработки среднестатистических WEB-проектов». Мой ответ — да, подходит. Но, как и в любой другой технологии, существуют трудности, с которыми придётся столкнуться. Начну я, пожалуй, с минусов, чтобы закончить на позитивной ноте.

Хьюстон, у нас проблемы

-1

Первое, с чем придётся столкнуться при разработке на Node.JS — это отсутствие полноценной IDE, работающей из коробки. Конечно, существуют плагины для Eclipse и NetBeans, есть частичная поддержка и в других IDE. Но назвать их полноценными решениями на данный момент нельзя. Есть очень перспективная разработка Cloud9 IDE. Она представляет из себя IDE для разработки на JavaScript прямо в браузере. Эта IDE быстро развивается и уже активно используется многими Node.JS разработчиками, но при этом, по моему субъективному мнению, она пока не готова для работы над большими проектами, хотя для написания небольших модулей использовать её очень удобно. За время работы над проектом я сменил не одну IDE. Начал с notepad++, долгое время использвал Cloud9 IDE, пробовал и другие, названий которых уже не вспомню, но в конце концов вернулся к NetBeans. Хоть там и нет поддержки Node.JS API, но с чистым JavaScript там работать довольно удобно. Пока остаётся ждать и надеется на появления полноценной поддержки. Разработка такого плагина уже ведётся.

-2

Вторым неприятным моментом станет необходимость перезапуска приложения после внесения каждого изменения. Несмотря на существование утилит, автоматизирующих этот процесс, некоторое время на это всё равно уходит. Так же быстро, как на PHP, внести изменение и сразу увидеть результат не получится. Однако, приложение перезапускается достаточно быстро — от одной до нескольких секунд, в зависимости от используемых модулей. В этом Node.JS, несомненно, выигрывает у Java — там перезапуск серьёзного WEB-приложения происходит намного дольше.

-3

Следующей проблемой, с которой столкнутся начинающие Node.JS разработчики, будет, скорее всего, утечка памяти. За памятью надо следить всегда и везде, но быстро живущие PHP-скрипты или небольшой клиентский JavaScript сильно расслабляют. В таких приложениях многие разработчики особо не предают значения потере нескольких килобайт памяти, а некоторые вообще не следят за этим показателем. Node.JS таких поблажек не делает. Приложение на Node.JS работает долго, и в случае утечки, каждый запрос к сайту будет уносить с собой кусочек памяти, которая очень быстро закончится, что приведёт к известным последствиям. Специфика JavaScript также располагает к появлению этого типа ошибок. Одно лишнее замыкание в большой области видимости или один потерянный var могут подарить Вам незабываемые часы дебага. Но в этом есть и плюс — такой опыт заставит любого разработчика ценить память и контролировать её использование при программировании на других языках. Лично я не считаю эту особенность минусом.

-4

Ещё одна особенность, которая доставляет неудобства — это возврат ошибок из асинхронного кода. Для сравнения, в PHP весь код выполняется синхронно, поэтому отловить ошибку на любом уровне вложенности можно с помощью конструкции try-catch. Мы можем завернуть в неё работу контроллера и при возникновении исключительной ситуации сделать throw, и ошибка «всплывёт» к ожидающему её обработчику, который покажет пользователю красивую страничку позора. Несмотря на то, что в JavaScript тоже есть конструкция try-catch, нам она не поможет, т.к. большая часть кода работает асинхронно (операции ввода/вывода). При этом исключительные ситуации, как правило, возникают не при вызове метода, а при работе его callback`а, который выполняется уже вне конструкции try-catch. Для передачи информации об ошибках в Node.JS принято использовать первый параметр callback-функции. Т.е. если у нас возникла ошибка, мы вызываем callback-функцию либо с одним единственным параметром, описывающем её, либо первый параметр выставляем в undefined/null, а в последующих передаём результаты работы нашего функционала. В реальных приложениях вложенность вызовов может быть довольно большой и каждый раз передавать ошибку наверх очень неудобно. Полагаю, что проблему всё же можно решить, применив AOP, но это тема выходит за рамки данной статьи.

-5

Также заставят понервничать и самые простые ошибки, которые довольно часто добираются и до production-сервера. Опечатка в имени переменной в очень редко выполняемом блоке кода может привести к остановке всего сайта или одного из процессов, если используется cluser api. Чтобы избежать подобных неприятностей, можно использовать утилиты, мониторящие работу приложения и перезапускающие его при необходимости, но настоящие ниндзя просто хорошо тестируют свой код (хотя никто не застрахован от ошибки в стороннем модуле).

-6

Последнее, что хотелось бы добавить — сложные математические расчёты не для Node.JS. На эту тему на хабе уже был очень флеймовый топик и смысла повторять тут всё, что написано в нём и комментариях к нему я не вижу. Скажу только, что у автора топика (конечно же, я имею ввиду автора оригинала, а не перевода) проблемы с выбором технологии, либо он просто троль. В Node.JS всё же возможно производить сложные математические расчёты, путём разбиения задачи на короткие итерации, выполняемые за несколько витков event loop, но это уже извращения и фанатизм. Гораздо проще выносить такие задачи за пределы event loop или вообще выбрать другую технологию для разработки.

А ради чего всё это?

Если к этому времени у Вас не возник такой вопрос, значит Вы либо опытный JavaScript-разработчик, либо поисковый робот, либо Чак Норрис (здравствуй, Чак!). Для всех остальных я попытаюсь описать преимущества, которые даёт нам разработка WEB-проекта на Node.JS.

+1

Самым значимым преимуществом Node.JS я считаю асинхронный ввод/вывод и прозрачность работы с ним. В большинстве WEB-проектов самыми частыми операциями являются чтение данных из БД и их сохранение. Эти же операции обычно являются самыми медленными. Но далеко не всегда они зависят друг от друга, наоборот, в большинстве случаев они атомарны. Например, при добавлении нового комментария к статье, нам нужно:
  • Сохранить сам комментарий;
  • Обновить пользователя (например, количество комментариев у пользователя и дату его последнего комментария);
  • Обновить статью (аналогично обновлению пользователя);
  • Записать в лог результат запроса.

Все эти операции не зависят друг от друга и СУБД способна выполнять их одновременно. При синхронном выполнении, например в PHP, эти операции будут выполняться друг за другом последовательно, каждый раз ожидая завершения предыдущей. В Node.JS мы имеем возможность отправить все 4 этих запроса к СУБД «параллельно». На самом деле запросы всё же отправляются последовательно (поэтому я взял в кавычки слово «параллельно»), т.к. Node.JS работает в одном процессе. Но Node.JS не дожидается результата работы предыдущего запроса, чтобы отправить следующий. Временем отправки запроса, по сравнению со временем его работы, при этом можно пренебречь. Когда запросы выполнятся, будут вызваны callback-функции для обработки их результата. Эти вызовы будут происходить так же последовательно, как и отправка запросов, а результат их будет обработан несравнимо быстрее времени их выполнения. Таким образом, общее время работы с данными будет приблизительно равно времени работы самого долгого запроса + небольшой оверхед на отправку запросов и обработку их результатов. Но в любом случае это будет быстрее, чем сумма времени выполнения всех запросов при их последовательной обработке (оверхед на отправку запросов и обработку их результатов в этом случае тоже никуда не уходит).

+2

Второй очень приятной возможностью является то, что ответ клиенту можно (и нужно) отправить сразу же, как он будет готов, не дожидаясь завершения работы всей логики запроса. Вернёмся к предыдущему примеру. При добавлении комментария мы записываем в БД некий лог. Эта операция нужна нам, но не нужна пользователю для получения ответа. С Node.JS мы можем сформировать и отправить ответ, а потом доделать то, что нужно нам: записать логи, очистить кеш и т.п. Время ожидания пользователя, соответственно, уменьшается.

+3

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

+4

Процесс Node.JS живёт долго и обрабатывает все http-запросы внутри себя. Это значит, что для каждого нового запроса не выполняется инициализация, как, например, на PHP. Настройки загружены, соединения с БД и с кешем открыты, код скомпилирован и готов к работе. Благодаря такой архитектуре и гибкости JavaScript открывается огромный простор для различных техник оптимизации. Например, один раз разобрав шаблон, можно хранить его в виде функции, принимающей на вход данные и возвращающей готовый HTML. Или можно легко организовать локальное (для процесса) кеширование, наиболее часто используемых данных, что даст прирост в скорости работы с ними даже по сравнению с memcached. Да, для PHP есть решения, которые позволяют частично ускорить процесс инициализации — APC для op-code, поддержка постоянных соединений в FastCGI и т.п. Но при сравнении ускоренного процесса инициализации с его отсутствием в принципе — выигрыш всегда будет за последним.

+5

Вокруг Node.JS за его относительно короткую жизнь уже образовалась солидная экосистема, включающая сотни модулей и, соответственно, их разработчиков. Во многом благодаря удобству github сообщество имеет отличный инструмент для развития этой экосистемы, которое идёт семимильными шагами, и свой вклад в это развитие может внести любой желающий. С помощью таких инструментов, как The Node Toolbox и npm, процесс поиска, выбора и установки необходимых модулей становится простым и быстрым.

+6

Сам язык JavaScript и API Node.JS очень гибкие и лаконичные. Программы получаются компактными и легко читаемыми. Вы вряд ли увидите в них классы, состоящие практически целиком из геттеров и сеттеров, или десятки файлов с описаниями интерфейсов. Такие вещи, как замыкания и лямбда-функции, позволяют писать очень красивый код, однако при особом таланте разработчика способны превратить его в филиал ада.
Я долго смеялся, увидев сравнение производительности Java и Node.JS. Тут можно долго рассуждать и приводить различные аргументы, но я скажу просто, как думаю. В event loop'е я вертел такую производительность, если код программы при этом увеличивается в десятки раз. У меня есть опыт разработки большого WEB-проекта на Java + Spring Framework + Hibernate. Там 10 строк кода, красиво описывают то, что будет делать 11-ая. Грубо, конечно, но это приблизительно отражает ситуацию. Возможно, для какого-то класса задач это и актуально, но не для среднестатистических WEB-проектов. Стоит добавить, что такое сравнение на «Hello world», не отражает реального положения дел. При появлении логики приложения, работы с БД, кеширования и других компонентов системы, сильно вырастает вероятность словить тормоза из-за не оптимального использования технологии, чем из-за её несовершенства. К тому же нужно помнить, что ресурсов сервера может не хватать в двух случаях:
  • Код написан плохо;
  • У Вашего сайта огромная посещаемость.
В первом случае поможет только выпрямление рук с последующим переписыванием кода и технологии тут совершенно не при чём. Во втором — у вас уже достаточно денег, чтобы купить ещё один сервер, т.к. это экономически более выгодно, чем поддержка в десятки раз большего объёма кода.

Заключение


Node.JS это не волшебная палочка. Это мощный инструмент со своими плюсами и минусами, который следует использовать только тогда, когда нужен именно он. Результатом своего эксперимента я доволен. Проект работает быстро, имеет простой и понятный код, который легко развивать и поддерживать. Несмотря на некоторые недостатки, Node.JS удобно использовать для разработки WEB-проектов и я верю в его развитие в этом направлении.

Продолжение следует


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

Спасибо всем, кто дочитал. Буду рад увидеть Ваши отзывы и мнения в комментариях.
Вадим @BVadim
карма
115,4
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (120)

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

    Про утечки памяти хотелось бы побольше.
    • 0
      Частично согласен. Транзакцией можно пользоваться, когда участок когда не очень критичен к производительности. Если же мы говорим об операции, которая выполняется очень часто многими пользователями и затрагивает несколько таблиц, при использовании транзакций всплывут тормоза и дедлоки. В таком выполнение запросов параллельно является техникой оптимизации. У нас же всегда остаётся возможность откатить действия, если один из запросов сработал с ошибкой, но такая ситуация будет возникать пренебрежимо реже штатной работы.
      • +1
        Я бы их все же серийно выполнял — если один провалился нет смысла выполнять остальные и проще отлеживать, а так лишнии строки кода.
        • 0
          Провал это очень редкая ситуация, которой, теоретически, вообще быть не должно. Нет смысла опасаясь её уменьшать скорость работы, учитывая то, что возможность отката всегда остаётся.
          • –1
            Победил.
          • +4
            Теоретически быть не должно, а практически бывает. И дальше — кропотливая и ужасная борьба с образовавшейся неконсистентностью. Так что транзакция. Тем более, что всё-таки запись в БД делается гораздо реже, чем чтение, и вот такие «оптимизации» очень сомнительны — лучше бы выборку кэшировали.
            • –1
              Абстрагируйтесь от комментариев. Я привел их ради простого примера распараллеливания задачи. Это может быть что угодно и акцент тут стоит, как раз, на очень частых операциях, которые транзакция погубит.
              • +2
                Ну насчёт чтения тоже есть пунктик — выведенные данные в редких случаях будут неконсистентными. Но на самом деле, на моей памяти как раз чтение данных обычно укладывается один запрос. Запись тоже должна была бы укладываться в один запрос, но мешает денормализация. А денормализация потому и делается, чтобы можно было данные в один запрос получить. Ведь чтение производится гораздо чаще.
    • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      А кто-то бы даже написал триггер, бррр…
      • 0
        Сильно скучно. Map/reduce наше все.
  • 0
    Расскажите, пожалуйста, подробнее про cloud9ide. Вы ее как-то настроили, чтобы она при тестовых запусках располагала исходники на вашем сервере?
    • 0
      Да, она ставиться очень просто:
      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 &
      

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      Библиотек много, качественные не все, но развитие идёт. Это нормально для молодой платформы. Всё будет.
      • 0
        Вычисления не обязательно должны быть сложными, они вообще не обязательно должны быть «вычислениями», если вы понимаете, о чем я. Это могут быть любые операции, которые выполняются довольно часто, либо постоянно. Держать их в одном процессе вместе с веб-сервером будет накладно, а в некоторых случаях — невозможно.
  • 0
    >Несмотря на то, что в 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# итд нет никаких проблем по работе с асинхронным вводом/выводом. Джаваскрипт я бы в этот список ни за что не добавил, тк в нём неудобно работать с асинхронным вводом/выводом.
    • –1
      Приведённая Вами конструкция форкает процесс? Или как она работает?
      • +1
        создаёт две подзадачи db_query, приостанавливает работу текущей задачи yield (python generators) дожидаясь выполнения двух db_query.
        • 0
          Это понятно. Я про то, где работают эти 2 подзадачи? И может ли при этом основной процесс работать дальше (пока ждёт их)? Принимать соединения и т.п.
          • 0
            Зависит от планировщика. Достаточно легко сделать как в нод.жс, будут эти подзадачи запускаться внутри одного треда и не останавливать этот тред на i/o операциях.
        • 0
          Боюсь, что асинхронность в вашем примере это многопоточность, а не асинхронность, как в Node.JS.
          Приостанавливать работу текущей «задачи» в Node.JS нельзя, поскольку общая задача выполняется синхронно в одном потоке, который ожидание результата (синхронное) просто остановит. Если не использовать фибру, например, или подобные пакеты.
          • 0
            боюсь что это обычная concurrency.
      • 0
        Это один из вариантов корутин на Python.
        Конструкция не форкает процесс а, говоря языком NodeJS, разбивает функцию home_page в месте где стоит yield на 2 функции с общими переменными, первая отработает сразу а вторая будет возвращена как коллбек.
        • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      JavaScript это нормальный язык, не менее нормальный, чем Python, который кстати на него довольно похож, например динамической моделью ООП. А описанное вами возможно только в случае, если асинхронный поток можно «слайсить» (я не знаю, какой тут термин подойдет) с помощью node-fibers, например. В tornado такой функционал является встроенным, хотя сам по себе не является частью «стандартного» асинхронного IO.
      • 0
        >А описанное вами возможно только в случае, если асинхронный поток можно «слайсить» (я не знаю, какой тут термин подойдет) с помощью node-fibers, например.
        node-fibers использует libcoro, а это достаточно неэффективный способ при условии если у нас будут сотни тысяч таких корутин.

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

      for page in home_pages():


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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

          >Обоснуйте, пожалуйста.
          weak/stong typing != static/dynamic
          Например в Си static weak typing type system
          • 0
            en.wikipedia.org/wiki/Strong_typing
            Javascript — weak, Java — strong
            Что не так с моим утверждением выше?
            • 0
              >Что не так с моим утверждением выше?
              «потому как этот код не может быть проверен до того, как будет выполнен.»
              «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)»
              • 0
                Вы придираетесь. Что ж, JavaScript не проверятся вовсе :)
    • +1
      Я считаю количество кода, особенно когда оно так различается, очень серьёзным аргументом. Можно долго говорить о различии в языках и в их предназначении. Но не нужно забывать, что приложение идёт в бой не одно, а в инфраструктуре. Кеширование и другие тхники оптимизации нивелируют нагрузку на само приложение. Обращаю Ваше внимание, что я не сравниваю зыки по скорости, я вполне допускаю, что Netty может реально выиграть эти 40% на hello world. Но в продакшн пойдёт не hello world, а готовая инфраструктура. Там будет не 1 поток node.js и перед ним, в большинстве случаев, будет стоять nginx. Для многих запросов, дёргать бекэнд node.js вообще будет не нужно. На такой инфраструктуре, даже если какой-то выигрыш у Netty останется, в чём я очень сильно сомневаюсь, мы получаем приложение с гораздо меньшим объёмом кода, который поддерживать дешевле (в человекочасах), а на сэкономленные деньги мы можем позволить себе, при необходимости, купить ещё один сервер (при этом продолжая экономить человекочасы на поддержку и развитие кода). Так-же обращаю Ваше внимание на то, что сейчас мы говорим о web-приложениях (будь то блоги, сервисы или браузерные игры). В данном контексте, чтобы сервер (я говорю о нормальном выделенном сервере) реально не справлялся с нагрузкой, нужно иметь посещаемость порядка 100к уникальных человек в сутки. В этом случае время на поддержку и развитие кода становится ещё дороже чем новая железка. Такая посещаемость у любого проекта будет далеко не сразу (если Вы не Google). А для быстрого старта гораздо важнее меньший объём кода, чем его сомнительный выигрыш в производительности, т.к. когда посетителей не много, оно будет быстро работать как на node.js так и на Java и на PHP и на всём остальном.
      • 0
        Вы меня не поняли: больше кода=дороже. Для PHP и JavaScript согласен, для Java нет.
        • 0
          Аргументируйте? C Вашей точкой зрения я вряд ли соглашусь, т.к. есть опыт разработки web-проекта на Java и поддерживать его гораздо сложнее чем проекты на PHP и JavaScript. Так же у меня нет цели кого-то убедить. Я высказал свою точку зрения и привёл довольно весомые, я считаю, аргументы в её поддержку. Соглашаться с ними или нет — дело каждого. Если хотя бы кому-то это поможет сделать правильный выбор — я уже не зря потратил время.
          • –2
            >есть опыт разработки web-проекта на Java и поддерживать его гораздо сложнее чем проекты на PHP и JavaScript

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

                    Nodejs — круто.

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

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

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