Pull to refresh

Comments 78

Статья, в целом, интересная, но не совсем понятен выбор MongoDB. Не лучше ли было воспользоваться Postgresql?
· Ваши данные так или иначе приведенны к какой-то структуре, соответсвенно один из плюсов MongoDB уже не важен.
· По операции INSERT Postgresql вроде обгоняет MongoDB (сам, конечно, не тестил, но по опыту работы с этими базами и вот этой статье blogs.enterprisedb.com/2014/09/24/postgres-outperforms-mongodb-and-ushers-in-new-developer-reality/)
· Ну и, плюсом, Postgresql экономичней относится к дисковому пространству.
Сравнительные тесты MongoDb vs реляционные базы данных сам не делал (а давно хотелось)
В этом проекте до написания внешней статистики (под внешней я понимаю то что данные передаются из браузера посетителя) была внутренняя статистика в нее данные пишутся напрямую из движка сайта (данных гораздо меньше, и они апдейтят различные индексы в уже созданных документах)
При каждом открытии веб-страницы движок сайта по окончанию генерации ответа делал несколько запросов в MongoDB на апдейт счетчиков
документы в монге имели вложенную структуру.
image
Реляционная база не позволила бы сделать такое и так быстро апдейтить такое количество счетчиков.
Получается уже был опыт положительный опыт работы с MongoDB (она хорошо себя зарекомендавала) также уже умели строить отчеты по данным из MongoDB
Поэтому во внешней аналитике было решено задействовать ее. В ходе разработки не раз менялся набор данных которые мы сохраняли (при старте не было Окончательного ТЗ) — с монгой в этом плане очень удобное — не нужно менять структуру таблицы, просто добавляй нужные данные и все.
Соглашусь с вами что в той аналитике которую я описал в рамках статьи MongoDB не дает никаких весомых преимуществ, вполне возможно что Postgresql в чем то бы ее сделал. Одно точно скажу что с Postgresql гораздо быстрее бы строились отчеты (опыт работы с SQL гораздо больший чем с NoSQL).
Спасибо за развернутый ответ. Т.е. в данном случае выбор MongoDB был только из-за положительного опыта её использования.
Кстати, в случае с php можно было решить проблему временного хранения с использованием второй СУБД развернутой в памяти, хотя это все равно медленне, чем хранение в памяти.
Медленнее, причем на много. Я в свое время делал такие эксперименты с php и Memcache
Memcache конечно очень быстр но не так быстро как nodeJS хранит у себя в памяти
Еще добавлю: на отдачу «helo World» nodeJS сьест ресурсов намного меньше чем nginx в связке с php-fpm
У монги очень хороший и удобный aggregation framework. На прошлой работе мы точно так же использовали ее для статистики в высоконагруженном проекте + куча правил аггрегации на все случаи жизни, что бы не хранить гигабайты сырой статы.
PID — уникальный идентификатор просмотра страницы, служит для того, чтобы сопоставить данные, которые пришли из stat.gif и p.gif.

Как и где генерился PID?
PID — уникальное поле, оно должно идентифицировать уникальный просмотр. Генерируется на базе уникального id пользователя (он генерируется на базе IP и еще некоторой инфы) + текущей юникс метки, UAgent, разрешения экрана и некой случайной величины.
Открыли страницу создался PID, тут же обновили эту же самую страничку у вас абсолютно другой PID будет.
Генерируется в яваскрипте на странице пользователя, уникальный id пользователя приходит с сервера через куки
— Какая у вас средняя нагрузка — сколько данных в среднем пишется в Монгу? Сколько онлайн юзеров?
— Был ли включен journal'инг? Резервное копирование, отказоустойчивость? А отказоустойчивость на уровне Node?
— Какая задержка до получения отчетов считается нормальной? Агрегация за прошлый день или максимально близко к realtime?
— Чем не угодила та же ГуглАналитика (или ЯндексМетрика)? Из того что вы написали, вроде, все можно ею сделать///
— Почему не стандартный для такого класса задач набор Apache Storm — Hadoop/Spark?
— Есть уже готовые счетчики, которые вполне поддаются кастомизации, например, Snowplow. Чем они не угодили?
— Каким образом вы обрабатываете ситуацию когда надо отправить некоторое событие, но юзер сразу же закрывает вкладку/переходит на другую страницу?
— Буферизируете ли вы данные перед отправкой (несколько «пакетов» собрать в один и послать одним запросом)?
— Как по-вашему, оправдано ли хранить данные для счетчиков в памяти?
— Вы хоститесь на своих серверах или облако? Если облако, то какое?
— Если облако, то пользуетесь ли всякими «хаками» для освобождения памяти, типа сброса кеша ОС, что повлечет за собой уменьшение потребление памяти Монгой?
— Каков максимальный размер массива с PID'ами?
— Где и как генерируется PID?
— Что будете делать, если одного сервера с Node станет недостаточно? Какая максимальная производительность, по вашим оценкам, у одного сервера?

Понимаю, что на некоторые из этих вопросов вы уже дали ответы, просто хотелось бы более подробного рассказа. Спасибо!
Много вопросов. Постараюсь ответить на некоторые из них
1. journal'инг — выключен — потеря данных этой статистики за несколько минут для этого проекта не критична
Отказоустойчивость Node — если вы работали с ней то знаете что любая мелкая ошибка в дочерних потоках — валит этот поток, а если в головном то и весь веб-сервер.
Решали следующим образом в головном потоке мониторились дочерние потоки и в с случае падения рестартились.
На случай падения головного потока использовался forever — если сервер падал он тут же его рестартил и ошибку с которой он упал писал в лог
2. Есть внутренняя статистика она пишет какие то элементарные вещи по трафику, она доступна в режиме реального времени, та которую я в статье описывал агрегируется с интервал в 1 час — этого было вполне достаточно.
3. Большой трафик, гугл и так использовал сэмплирование для построение отчетов + приходило письмо от них с просьбе снизить нагрузку на их сервисы
4.Apache Storm / Hadoop/Spark не знаком с ними, не пишу на JAVA
Изначально был большой опыт написания различного кода на php/MySQL /JS / HTML
в nodeJS синтаксис JS по большей части поэтому выбор пал в ее сторону.
5. Каким образом вы обрабатываете ситуацию когда надо отправить некоторое событие, но юзер сразу же закрывает вкладку/переходит на другую страницу?
никак не обрабатываем, данные теряются, для нас не критично потому что важен не конкретный юзер а картина в целом. Если это критично то можно увеличить интервал оправки данных или отлавливать событие закрытия страницы и отправлять в этот момент данные.
6.Данные не буферизуем
7.Считаю что оправдано хранить в памяти — так они апдейтяться практически моментально — если конечно данные не слишком важные и раз в месяц потеря данных за 1 минуту не страшна.
8. Сам сайт и статистика на одном сервере — статистика потребляет всего несколько процентов ресусров. Видео хоститься на CDN
9. Если посещаемость возрастет прямо на порядок (что очень маловероятно, проект довольно старый) то аналитику перенесем на отдельный сервер.
простите за занудство — но я так и не понял, скрипт передает статистику каждые 30 или все таки 15 секунд?
этот параметр задается в конфиге, На проекте с которого приводил цифры там стоит 30 секунд.
Поправлю в статье
Можете более подробно рассказать про storage.syncPeriodSecs? Как вы его в итоге настроили и как это отразилось на производительности?
Мы его настраивали когда файлы MongoDB хранились на обычном жестком диске. Сам процесс Mongod жрал много ресурсов — сказывались задержки от HDD. Увеличили время стал жрать намного меньше только изредка всплески в момент сброса данных на диск. C переходом на SSD необходимость настройки этого параметра отпала
А зачем здесь вообще мультипоточность, работа по http, когда задача решается тейлом в одном процессе лог-файла nginx, отдающего однопиксельный gif, зачем было изобретать весь этот велосипед?
Из плюсов подхода: нет никакой задержки на работу Вашего сервера при отдаче пикселя, возможность пережить падения сервера, запустив обработку с начала, возможность сразу отфильтровать запросы отличные от p.gif и stat.gif и т.д и т.п.
NodeJs рекурсивен, задержка на отдачу этой картинки не больше чем у nginx
Если делать так как вы предлагаете то пришлось бы этот лог файл писать где-то в оперативной памяти иначе бы nginx на таком количестве запросов замучал бы HDD и загнулся.
Я не думаю что на написание парсера логов постройки всей системы на базе nginx ушло бы на много меньше времени чем на реализацию всего этого на NodeJS
Код воркера — 56 строк, код сервера ~ 100 — и это с описанием подключения библиотек, объявлением переменных, отступами и комментариями.
Что значит «NodeJs рекурсивен»?
И почему запись в базу данных не замучает HDD, а в лог-файл замучает?

И да, Nginx всегда будет быстрее nodejs для статики (при правильной настройке).
Рекурсивен — имелось ввиду то что пользователю можно отдать заголовок 200 с телом ответа а данные по этому пользователю еще обрабатываются.
У меня данные не пишуться в базу при каждом HTTP запросе, они сначала агрегируються в памяти самого NodeJS и только когда перестают приходить новые данные вставляются в базу данных. Если вы заметили в статье пока у юзера открыта страница измененные даныне по нему приходят все время с заданным интервалом.
На счет отдачи заголовка и дальнейшей обработки — я бы это назвал отложенная обработка.
Агрегация в памяти это хорошо, но и Nginx не скидывает буфер в файл (лог) после каждого запроса, а делает это по таймеру или по мере заполнения буфера.
Nginx не скидывает буфер в файл (лог) после каждого запроса — это я знаю, тоже очень люблю nginx за его производительность.
Постараюсь найти ссылку на сравнительное тетсирование nodeJS и nginx. Хотя в принипе на отдаче однопиксельной картинки и самому не сложно его сделать. Там результаты должны быть очень похожими, другое дело что Nginx намного безотказней.
Между любым приложением и диском почти всегда существует не один буфер, поэтому скидывание на диск (sync) почти в любом случае происходит не сразу. Почти — это если приложение явно не просит сделать sync или открывает файлы с флагами типа O_DIRECT. Но это во-первых легко проверить (strace), во-вторых можно отключить, есть даже готовые тулзы — гуглим по «eatmydata».
Еще простой способ — писать логи на tmpfs раздел, и забирать их по мере необходимости/обработки.
1) Как связана рекурсия со скоростью отдачи картинки, не совсем понятно. Вы всю статику на сайте тоже NodeJS отдаете, потому что он рекурсивен или все таки nginx?
2) Даже SATA HDD не загибаются от записи на скорости порядка 50-500Кбайт/с в один поток
3) Формат логов nginx описывается в его конфиге — хотите пишите в csv, хотите в формате query_string, хотите в json и именно то что нужно — соответственно никакие специальные парсеры писать не нужно
4) Значит вы свой код сократили бы примерно на 2/3 (код сервера) к затратам же по времени добавили бы 10-15 секунд на добавление описания access_log-а в нужном формате в конфиге nginx

P.S.: можете и дальше продолжать забивать гвозди микроскопом, разубеждать Вас в этом у меня нет ни сил, ни желания
Что Вы такой нервный? :)
В этот лог будут писаться несколько тысяч, точнее несколько десятков тысяч сессий. По одной строчке каждые 15 секунд от каждой сессии. Конец сесссии — непрогнозируемый. Как этот лог разбирать и самое забавное — ротировать?
Одна строчка в логе — это хит, а не сессия, сколько их там забота обработчика.
Методика обработки лога ничем не отличается от алгоритма, описанного в статье, вешается watcher на событие «запись в файл», полученная пачка данных обрабатывается, процесс спит или занимается своими делами до следующего события «запись в файл». Следить нужно именно за записью в файл, а не файловый дескриптор.
Грубо и в лоб это решается открытием пайпа «tail -F access_log_name |», я не знаток NodeJS скорей всего есть стандартные событийные библиотеки такого рода, опять же в лоб можно обойтись стандартными средствами — stat на файл, с памятью предыдущего состояния.
Проблем с ротацией нет никаких, можете использовать стандартные средства, например syslog.
По поводу дисскуссии: под вечер голова чугунная я перепутал термин асинхронность с рекурсией.
P.S. просто при асинхронном коде часто рекурсия используется
P.P.S. по поводу вашего скептицизма насчет NodeJS — вот пример теста сравнивающего Nginx и NodeJS при отдаче статики. Такой тест в принципе не сложно самому сделать, елси будет время на выходных попробую сам сделать антологичное сравнение + предоставлю конфиг Nginx и код NodeJS.
Повторюсь я не в коем случае не агетирую за отдачу статики на сайтах через NodeJS — лучше nginx на сегодняшний день в этом плане ничего нету.
Приведенная выше ссылка — это сравнение сферического коня в вакууме, в стиле «Hello World», реальная нагрузка на веб-сервер при обработки статики не ограничивается отдачей одного файла.

В данной конфигурации «железа» у nginx для целей отдачи статики вокеров должно быть не более двух, конкретно в этом примере лучше 1, размер файла в 33 Кб выбран не случайно, чтобы «пролететь» мимо стандартных 32Кб буферов, кэширование файловых дескрипторов наверняка отключено, включено ли aio и sendfile и т.д. и т.п. — т.е. без конфигов и кода сервера на NodeJS это бессмысленно, может файл вообще в памяти в кэше NodeJS процесса осел. Особенно умиляет CPU-usage который в случае с NodeJS как минимум в 50 раз выше, что частично подтверждает догадку с кэшем в памяти :)
может файл вообще в памяти в кэше NodeJS процесса осел

Ну если бы я писал то именно оттуда и отдавал бы файл)
Нет желания сделать конфиг nginx под такую задачу?
я бы потом на том же сервере запустил бы код NodeJS и сделали бы замеры?
Без эксперимента — спорить/обсуждать можно очень долго)
UFO landed and left these words here
1) Как связана рекурсия со скоростью отдачи картинки, не совсем понятно.
напрямую
пример
получили GET запрос, вставили данные в базу, отдали картинку, закрыли соединение
и
получили GET запрос, отправили рекурсивный запрос на обработку данных(не ждем результата идем дальше) отдали картинку, закрыли соединение,
2) Если вы имели дело с высоко-нагруженными проектами то наверно замечали если какой то процесс сильно нагружает диск — то тормозит практически вся система
3) не получилось бы так у меня скрипт отстукивает с одной открытой страницы через каждый 15 (30 в зависимости от настройки) секунд — и если делать так как вы предлагает то ваш лог файла в конце дня будет весить десятки гигабайт а возможно и больше.
4) Готов поспорить с вами вы не напишете access_log за 15 секунд в нужном мне формате

вы перепутали слово асинхронность и рекурсивность
Да вы правы… Как перед человеком неудобно (
Спасибо что поправили!
1) nginx тоже «рекурсивен» (асинхронен) и почему один «рекурсивный» сервер должен работать не медленнее другого «рекурсивного» сервера у меня в голове не укладывается — вспоминается легендарная фраза из мультика «А в попугаях то, я гораздо длиннее !!!»
2) Еще раз повторю, что если запись ДО 500 Кбайт/с в ОДИН поток, для Вас является высокой нагрузкой — то мне Вас жаль — современные SATA диски способны справиться с нагрузкой выше на 2 порядка, а SSD на 3 порядка
3) Да, для 2014 года файл на десятки гигабайт это мега-объем, но если это проблема, то его можно ротировать раз в час / 15 минут например, если данные не важны — удалять, если нужны — архивировать :)
4) В стандартном формате, перечисленным выше — напишу, в нужном Вам — может быть займет чуть больше — все описывается элементарно — можете ознакомиться сами nginx.org/ru/docs/http/ngx_http_log_module.html#log_format :)

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

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

Я не сопротивляюсь.
О том что nginx надежен как «автомат калашникова» я не собираюсь с вами спорить и опыт наработанный админами годами тоже не отвергаю.
Я не думаю что производительности решение на Nginx Будет быстрее.
А вот елси немного усложнить задачу и добавить условие чтобы счетчики обсчитывались реалтайм то Nginx — вовсе не справиться.
Вам как админу просче было бы решить эту задачу посредством nginx мне как программисту через NodeJS — вот и вся разница
> А вот елси немного усложнить задачу и добавить условие чтобы счетчики обсчитывались реалтайм то Nginx — вовсе не справиться.

Вы еще раз прочитайте, то что я написал — счетчики как раз и обрабатываются realtime
статику можно (и нужно) разложить на cdn и логгировать там (на уровне nginx), это дополнительно размадет обращения к диску (да и single point of failure уберет)
логи потом можно сливать в один большой, препроцессить хадупом (сливая вместе запросы к p.gif) и класть например в Cloud Storage
тогда все отчеты можно было бы получать простыми sql-like запросами BigQuery
А как в случае tail… решать вопрос с масштабируемостью?
Делать балансер по ИП? по какой-то сессии?
Какой бы вы посоветовали подход в этом случае?
Ну здесь может быть несколько подходов:
— если обработчик логов справляется на одной машине, то tail отправляет лог на лог-коллектор, где происходит обработка через тот же tail например — я думаю сотни миллиардов «хитов» такая связка в состоянии обработать
— если обработчик на одной машине не справляется, то tail делает пре-процессинг выявляя из записи в логе PID и делая балансировку лога на соответствующий лог-коллектор — при таком количестве «хитов» можно уже посадить отдельного человека и написать модуль для nginx, чтобы лог-запись сразу попадала в «правильный» лог-файл (один из н-цати, по количеству лог-коллекторов)
А чем отправлять на лог-коллектор?
у меня почему-то в голове тоже вещи вроде mq, но я не уверен что они могут делать tail лога
Как сейчас обстоят дела с precess.send? раньше оно могло вызывать затык в обмене сообщениями между кластер процессами.
Да вроде бы как в новой так и в старой версии NodeJS он работает одинаково
«Миллион одновременных соединений на Node.js» — можете почитать эту статью там автор делает замеры времени передачи тиков (они как раз этим методом отправляються)
1. Можно было бы просто собирать данные за некоторый период (например день) в памяти (ОЗУ) с помощью memcached, TABLE MEMORY и т.п., а по истечении периода сбрасывать их роботом в SQL базу на диске для анализа.
2. Вы писали: «У одного пользователя может быть открыто сразу несколько таких страниц и все они будут отправлять данные вне зависимости от того, пользователь на этой странице сейчас или нет» — на лицо ошибка проектирования системы. Логично собирать только данные об активности пользователя, а фиксировать простои или неактивные сессии смысла нет. Как результат ненужная избыточность данных и повышенная нагрузка на Вашу систему статистики.
Это не ошибка проектирования — так было задумано — эти данные важны. Есть категория людей которые любят открывать сразу много вкладок в браузере даже могут в некоторых запустить видео плеер (выключить звук или поставить видео на паузу чтобы качалось) — инфа по этим пользователям также важно. И пользователь может открыть вкладку потом уйти с нее на другую страницу и потом вернуться.
Только в памяти собирать было бы совершенно неправильно — потеря питания — и вся статистика за сутки пропала, но использовать что-то вида memcachedb или redis было бы более логично, для задачи такого рода — MongoDB тут явный оверкилл.
Вы немного не поняли: оно собирает в памяти данные только на 1 просмотр. т.е если вы включили компьютер и оставили страницу открытую на целый день она будет собирать по вашем просмотру данные в память целый день.
Если вы открыли страницу и через минуту перейдете на другую страницу в nodeJS будут данные в памяти собираться по вашему просмотру только эту минуту и когда вы перейдете на другую страницу они вставятся в MongoDB.
P.S. Вру — целый день не будет собираться, сработает ограничение по времени 2 часа и данные вставятся а по вам будет считаться что вы закрыли страницу.
Мой комментарий относился к первому пункту ораторас предложением использовать memcached или in-memory таблицы, он никак не относится к Ваше методике обработки информации.

И даже при вашем подходе при сбое питания (ну или например перезагрузке процесса NodeJS, его корке и т.п.) будут 100% потеряны данные за последние 90 секунд и тех кто не проявлял активности (совершил запрос только на stat.gif) за последние 2 часа.
Да именно так.
будут 100% потеряны данные за последние 90 секунд и тех кто не проявлял активности (совершил запрос только на stat.gif) за последние 2 часа.

В данном проекте это было не кретично
Глаз зацепился, не могу оторвать…
image = fs.readFileSync('p.gif');

… прям в середине асинхронного кода.

Как это понимать?
1. Если был хотябы 1 запрос к сереру то картинка уже не грузиться из системы
а отдаеться из памяти
 if(image == undefined){


2. Считывание картинки обернуто в асинхронный метод
fs.stat('p.gif', function(err, stat) {   //  Проверяем  существует ли файл 
                    if (!err){   елси  нет ошибки считываем и отдаем 
                        image = fs.readFileSync('p.gif');
                        res.end(image);
                    }
                    else
                        res.end();
                });


В 99.99% случаях картинка отдается из памяти
1. fs.exists — проверка на существование файла
2. Что Вам помешало написать вместо этого
image = fs.readFileSync('p.gif');

вот это

fs.readFile('p.gif', function(err, data){
  if (err}{ return; // TODO }
  image = data;
});


Никогда не вызывайте синхронные методы после того как «процесс пошёл».
К тому же, закэшировать картинку в памяти можно при старте приложения. Вот там, кстати, можно воспользоваться синхронным методом.
Тоже глаз режет) Такой поворот мне не ясен, обязательно должен быть callback.
Почему, например, нельзя взять только Nginx и по крону агрегировать и архивировать его логи, а данные класть в любую БД.
Не совсем понятно зачем эти хаки с Node…
Выше в комментариях уже обсуждается, не прочитал весь тред. Сорри…
UFO landed and left these words here
Сейчас такие вещи делают на fluentD, Kafka, Amazon Kinesis
Судя по разным показателям, это сайт с взрослым контентом. Я угадал?)
Мне нельзя вам называть имя сайта. У вас хорошее чувство интуиции)
может, я чего-то не догоняю, но как дергать картинку p.gif, каждые 30 секунд, без аякса?
1. Если вы будете делать AJAX запросы со своего сайта на другой домен — придется решать вопросы с кроссдоменностью (в принипе не сложно — отдавать нужные заголовки и прописать crossdomain.xml)
2. Нельзя использовать jQuery, а без него самому описывать AJAX запросы очень проблематично
3. Важно было чтобы это работало в самых древних браузерах

var img=new Image(1,1);
img.src='http://blablablbla';
img.onload = function() {//  картинка загрузилась, модем   запустить таймер еще на 30 секунд  собрать данные и отправить снова}; 
// Все очень просто
Как нибудь посмотрите в сторону Go и/или InfluxDB.
Имею очень положительный опыт с Go + MongoDB, а InfluxDB может лучше подойти для данных, с которыми вы работаете.
Также, Go идеально подходит для описанной задачи и требований.
Перечитал статью, на Go эта задача решается элементарно и код был бы чище (т.к. есть возможность писать синхронный код), меньше, это все было бы намного проще деплоить и кушало бы меньше ресурсов.

Та же асинхронность, перспективность, очень простой синтаксис и простота написания кода для конкретно этой задачи еще выше.

Мне стало интересно, я бы не отказался написать аналогичный сервис на Go и сравнить ключевые для вас показатели.
Уверен, что это было бы даже проще, чем чтение логов nginx-а, которое предлагается в комментариях.
Может сделать какой-то синтетический тест по отдаче картинок и вставки данных в базу и сравнить по ресурсами nodeJS. Go и Nnginx?
Сейчас я и думаю, как бы это сделать.
На reddit уже делали сравнение производительности Go и Nginx, примерные результаты — Go ~140-150k rps, против nginx ~160-180k.
Nginx быстрее, но не так уж сильно.
Сейчас я пытаюсь разобраться в предметной области и написать простенький демон на Go, который делает то, что описано в статье.
Я на это обсуждение и ссылался.

В том же реддите
«91255.00 req/s for Golang» vs «NGINX scales at 142618.31 req/s»
И
«Tried it with wrk and not ab now, and with nginx echo. Go does ~140-150k rps, nginx does ~160-180k rps»

И при дальнейших оптимизациях конкретно отдачи статики:
www.reddit.com/r/golang/comments/28so0e/go_networking_performance_vs_nginx/cif19e1

Ну так, а попробуйте оптимизировать конфиг nginx и получите еще больше. Но на самом деле там дальше nginx уже упирается в клиентское приложение. Клиента нужно запускать на более мощной машине или на нескольких, либо отводить под него большее количество ядер процессора, поскольку клиентские вызовы обычно дороже, а нам нужно обеспечить, как минимум, двухкратный запас ресурсов.
И никаких «Socket errors» при тестировании быть не должно, ибо это верный показатель, что что-то не так делается, недонастроено или неисправно.

Ещё один забавный момент, там у человека:
nginx: 63697 requests in 2.00s, 17.86MB read
Go with a cached file server: 118962 requests in 2.00s, 13.17MB read
— значит запросы сильно разные, nginx отдавал существенно больше.

Почти во всех случаях, когда Go догоняет nginx — это просто неграмотно поставленный тест. =)
В большинстве случаев сервер Go ставится за nginx и занимается явно не простой отдачей файлов или статичной строчки, ну и я полностью согласен с тем, что если встроенный файловый сервер Go догоняет Nginx, то тут действительно что-то не так.

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

Я вообще считаю, что тема производительности go vs nginx как минимум слегка оффтопик, а как максимум — не имеет смысла :)
А что конкретно тестировать?
Время на отдачу одной картинки, количество занятой памяти в зависимости от размера кеша, скорость вставки в монгу?
А что конкретно тестировать?
Время на отдачу одной картинки, количество занятой памяти в зависимости от размера кеша, скорость вставки в монгу?

Если в тесте будет Nginx то думаю можно разбить его на 2 раунда
в Первом nginx NodeJS и GO — просто отдача картинки (nginx не умеет же работать с базой, да и не его эта задача)
Во втором NodeJS и GO все тоже самое + вставка данных в базу
по тестам думаю стоит замерять:
1. Время на отдачу картинки
2 Количество запросов с которыми справляется
3. Потребление ресурсов.
А обязательно отдавать именно картинку?
Если вы используете ее лишь из javascript, то достаточно любого ответа 2xx с image/gif, разве нет?

Ну и я достаточно мало работал с nodejs, так что вряд ли смогу написать адекватный тест.
Может, поможете с этим?
Для серверной части не пробовали посмотреть в сторону Erlang? Для современных браузеров можно использовать web sockets, для древних простые http запросы. Код серверной части усложнился бы, но оно того стоит. При использовании OTP была бы чуть посложнее архитектура, но взамен приходит надёжность OTP приложений. Описываете application, супервизора и воркеров, далее erlang сам следит за тем, чтобы они всегда работали. Простой пример создания tcp сервера, не самый лучший, но принцип понять можно.
Почему PID нельзя генерировать на сервере при первом обращении и сохранять его в cookie?
Можно на сервере, можно в браузере — не принципиально.
За время работы в продакшене не было проблем с SSD? На мой взгляд при вашей схеме работы менять вы их будете раз в 1-2 месяца.
На удивление не было проблем(может быть из за того что MongoDB данные на диск раз в 40 секунд сбрасывает). Уже второй год SSD на том же сервере честно трудиться. Попробую узнать какая модель стоит.
Были проблем с SSD на домашнем компьютере (Vertex 3) через 4 месяца после покупки начались сбои и потери данных.
Также на другом проекте на серверах с отдачей видео используется SSD — на нем nginx кэширует часто отдаваемые файлы, вот там были проблемы, правда и SSD кажись довольно дешевые были.
Only those users with full accounts are able to leave comments. Log in, please.