Доброго времени суток. Мне хотелось бы поделится с хабросообществом о своем опыте использования Node.JS на живом проекте. Пять месяцев назад я начал воплощать одну из своих старых задумок — сервис достижений.
При разработке проектов я предпочитаю придерживаться точке зрения, что выбор технологии должен быть обоснован дешевизной ее использования. Поэтому для своего проекта я выбрал стек — Node.JS + mongoDB, так как это те технологии, которыми я лучше всего владею.
Хочу заметить, что здесь я буду описывать только те проблемы с которыми сталкивался сам.
Принудительная Асинхронность
Node.JS известен своей идеологией в том, что все вызовы I/O должны происходить асинхронно. Такой подход предоставляет очень широкие возможности, хотя иногда и приводит к определенным проблемам. Например банальная ситуация — необходимо сделать запрос к БД и на основе результата сделать еще один запрос, например в другую таблицу. По религиозным причинам я не использовал mongoose(ORM для mongodb). В связи с этим использовал node-mongodb-native. Проблема в том, что при использовании этого модуля приходится работать с курсором БД, что приводит к появлению лишнего колбэка:
db.collection('table', function(err, collection) {
collection.findOne({uid:uid}, function(err, doc) {
cb(doc);
});
});
Таким образом описанная выше задача сводится к банальному колбэк хэллу:
db.collection('table', function(err, collection) {
collection.findOne({uid:uid}, function(err, doc) {
db.collection('table2', function(err, collection) {
collection.findOne({size:doc.size}, function(err, doc) {
cb(doc);
});
});
});
});
Подобные проблемы принято решать посредством использование Coffescript или модуля async оба способа делают код более читаемым и адекватным. Как промежуточнее решения я разделил вызовы на функции — такой вариант приводит код в более или менее вертикальный вид, но так же, при достаточно длинной цепочке вызовов создает проблему отслеживания ошибки в этой самой цепочке.
Дебаггинг
Крашлог в Node.JS в общих задачах не вызывает никаких претензий, но иногда выпадают эксепшены по которым, не ясно в чем ошибка, ясно только то что она есть.
events.js:71
throw arguments[1]; // Unhandled 'error' event
^
Error: socket hang up
at createHangUpError (http.js:1264:15)
at Socket.socketOnEnd [as onend] (http.js:1352:23)
at TCP.onread (net.js:419:26)
По такому логу ясно что ошибка в вызове модуля http. А если в приложении больше одного вызова http? Какой из них вызвал ошибку не ясно. Приходиться смотреть уже логи на другой стороне.
Forever
Разработчики использующие Node.JS наверняка знакомы с модулем forever. Этот модуль позволяет запускать node процессы и отслеживать его краши. Но проблема состоит в том, что forever форкает себя для отслеживания каждого запущенного вами приложения. В итоге в топе мы видим N количество процессов ноды, и не ясно какой из процессов сколько ресурсов потребляет. Pid конечно можно получить из forever list, но это неудобно.
Отлов ошибок
Сам Node.JS и многие модули к нему придерживаются концепций CommonJS в частности то, что ошибки исполнения функций должна быть возвращена в колбэке первым аргументом. В связи с этим ошибка возможна после каждого вызова I/O, что может привести к эксепшену. Значит необходимо обрабатывать каждое исключение(за это кстати постоянно «пинают» Node.JS =) ). Так как мой проект находится на стадии «глубокой» беты такие проблемы я решаю «на живую» т.е. обработка ошибок реализовывается только тогда, когда она начинает возникать. Так как приложение имеет модульную структуру такое позволительно — пользователь не видит никаких ошибок.
Вот пожалуй и все. Стоит заметить, что хоть я и описал только отрицательные стороны Node.JS с которыми я столкнулся, но все же для меня положительных моментов гораздо больше) Всем спасибо за внимание)
P.S. Если кому интересно ссылка на проект.
Автор: baboon