Comments 77
>> очень низкая у apache+php, это когда сервер апач при каждом запросе читает с диска php-скрипт и выполняет его
Простите за резкость, но зачем этот бред в статье? Никто уже не использует Apache + PHP таким образом. Для работы PHP стандартное решение это FPM (Fast CGI Process Manager) плюс, к примеру, nginx перед ним. И поверьте, это ничуть не медленнее и ничуть не уже по пропускной способности, чем условная NodeJS в задачах "Сделать запрос к БД, отдать JSON". А уж про память и говорить нечего - разница будет на порядок не в пользу NodeJS.
Никогда не понимал, в чем же на самом деле преимущество, за которое так топят сторонники node, go и прочих альтернативных технологий: запихнуть в одно целое сервер приложений, менеджер процессов/потоков и прикладной код. да еще и заставить одних и тех же людей их писать? Вы действительно считаете, что напишете nginx лучше Сысоева? )))
В node, go, асинхронном python, асинхронном rust и прочих асинхронных аналогах «сервер приложений, менеджер процессов/потоков» в принципе не нужны — одно лишь это уже является жирным преимуществом перед тем же FPM
(Впрочем, менеджер процессов/потоков иногда имеется, но он опционален)
Вот здесь я с вами категорически не согласен. Они не "не нужны", их просто приходится придумывать самим. Силами программистов, чья квалификация по определению ниже, чем квалификация тех, кто создавал nginx или PHP-FPM.
Не приходится, потому что они не нужны. Вы не знаете, как работает асинхронщина?
Учитывая, что я статью писал с объяснением этого понятия для начинающих, нет, наверное, пока до конца еще не знаю ))
Очень жаль, если бы вы прочитали свою статью, то узнали бы про event loop, который делает «менеджер процессов/потоков» ненужным в большинстве задач)
Придумывать свой собственный event loop, разумеется, не нужно, уже есть сотни готовых реализаций, написанных людьми с квалификацией уровня примерно того же Сысоева, просто берём и пользуемся
Ну а «сервер приложений» настолько не нужен, что даже не упоминается там)
Либо у вас путаница в голове, либо вы слишком скомкано пишите.
Event loop (ноды), управляет асинхронными задачами в рамках одного потока, а менеджер потоков, что понятно из названия, управляет потоками (паралелит, балансирует, обеспечивает передачу данных между ними и т.д.). Как человек, который много писал на C# и хорошо знаком с работой потоков (не путать с асинхронностью, это не одно и тоже), немного не понимаю ваш тейк, что якобы event loop делает менеджер потоков, не нужным. Это 2 разных инструмента, которые используются на разных слоях приложения. В той же наде насколько я помню, потоки под капотом тоже используются, например для работы с файлами.
Так же для организации асинхронности event loop не всегда используется в разных яп. У C#, C++ и Java для асинхронности используются другие инструменты и подходы. Даже в Go о котором в статье речь используется насколько помню goroutine manager или как-то так.
В начале ветки поставлена задача «Сделать запрос к БД, отдать JSON», в которой из нагрузки на процессор разве что (де)сериализация. Какой смысл параллелить и балансировать околонулевую нагрузку? Есть подозрение, что на накладные расходы может потеряться больше)
В синхронных веб-приложениях «менеджер процессов/потоков» решает проблему вида «ой, воркеры кончились и принимать запрос некому», в то время как в асинхронных такой проблемы изначально нет, потому что event loop способен принять и обработать условно бесконечное количество запросов. Потоки и тем более процессы ему просто не требуются, пока не объявится какая-нибудь серьёзная cpu-bound задача или лютый highload
потому что event loop способен принять и обработать условно бесконечное количество запросов. Потоки и тем более процессы ему просто не требуются, пока не объявится какая-нибудь серьёзная cpu-bound задача или лютый highload
Побуду занудой. Event Loop'у нужны потоки, ибо в них он и работает. И по умолчанию себе берёт кол-во потоков равное найденным физическим процессорам. И они ему нужны даже если он выполняет простые не cpu-bound задачи.
Другое дело cpu-bound задачи - исполнять их в потоках Event Loop глупо - это приводит к блокированию работы этого лупа. Для таких задач все фреймворки позволяют использовать выделенные потоки.
Event Loop'у нужны потоки, ибо в них он и работает.
Зависит от реализации. Стандартные event loop'ы в тех же Python и Node.js принципиально однопоточные и раскидывать задачи по потокам не умеют от слова совсем. Tokio runtime в Rust предоставляет Current-Thread Scheduler, который, как понятно из названия, работает в одном потоке и позволяет программисту не заботиться о возможном перекидывании задач между потоками.
Конечно, при всём при этом никто не запрещает закидывать cpu-bound и другие синхронные задачи в какой-нибудь пул потоков, но «это другое»™
Tokio runtime в Rust предоставляет Current-Thread Scheduler, который, как понятно из названия, работает в одном потоке
Немножко не так. По умолчанию Tokio использует Multi-Thread Scheduler. Чтобы задействовать Current-Thread Scheduler нужно немного поработать ( подключить feature "rt"). Вот выдержка из документации:
The multi-thread scheduler requires the rt-multi-thread feature flag, and is selected by default.
...
The current-thread scheduler provides a single-threaded future executor. All tasks will be created and executed on the current thread. This requires the rt feature flag.
К сожалению, на Хабре это уже давно не аргумент. Я тут столько статей видел от раскручивателей собственного бренда, плохо понимающих в теме
... их просто приходится придумывать самим
Но зачем? Есть готовые решения. В том же Rust - это actix, к примеру. И прикладному разработчику остается только реализовывать бизнес логику повесив ендпоинты на сответствующие спецификации URI.
Зачем сейчас в Go, Rust, да вообще в любом языке прикладному разработчику писать "сервер приложений", "менеджер процессов/потоков" - всё давно уже написано и отлажено за нас.
отдавать статику через нод плохая иде и так делают только в туториалах для express.js . nginx будет раздавать статицук и роутить запросы а нод будет их обрабатывать . действительно написать вебсервис на ноде проще простого . и есть большое количество библиотек и фреймворков для этого . Можно писать и на пхп. но это просто еще один из хороших способов решить проблему написания вебсервисов
Зависит от нагрузки. Раздача статики от ноды на самом деле может быть очень даже хорошая идея, потому что позволяет быстро деплоить простой сервис. Не дай бог мне на каждый мелкий сервис настраивать какой нибудь http сервре.
а что там настраивать ? в типичный docker-compose.yml добавить блок с nginx c проборошенными 80 и 443 портом и замапленным конфигом сертификатом и папкой с статикой
Даже nginx не нужен, в docker-compose прописываем бесконфиговый caddy-docker-proxy, через labels пишем простейшую маршрутизацию в соседний сервис в три строки - он сам и серты поднимет, и логи пропишет, и ошибками займётся.
Говорят, Traefik настраивается аналогично, но я до него не дорос - как увижу, что для него под 30+ лейблов прописать надо, так сразу окстюсь и отхожу подальше.
В статье была ремарка о Fast CGI, но я удалил её т.к. статья совсем не об этом, но для вас вернул на место
с типизацией все еще беда, поэтому сложно написать сразу рабочий код не запуская его не разу
Запустить параллельные несколько асинхронных операций на node проще. Можно делать сетевые запросы в несколько потоков или запустить тяжелю задачу в worker сразу на 32 ядрах.
При запуске сервера тяжелые объекты можно инициализировать 1 раз и моментально выдавать ответы на запросы к api из оперативной памяти
Я не видел ни одной статьи, где переписывают код с go, node etc на php, и каждый месяц выходят новые как переход с php на whatever поднял rps с 2000 до 30000. И да, писать nginx там не нужно, просто хедлер подсунуть фреймворку и радоватся жизни.
Преимущество в чем перед пыхой? Хмм, дайте подумать, на пару ноликов больше запросов в секунду, как вам такое? Возможность шеринга кода с клиентским приложением для ноды, это самое главное.
"Никогда не понимал, в чем же на самом деле преимущество, за которое так топят сторонники node, go и прочих альтернативных технологий" - например, как вариант, сделать на PHP демона (или полноценное приложение реалтаймовое), который будет читать сообщения из кафки или работать с вебсокетами напрямую и при это так-же стабильно работать, может быть проблематично или практически не реально (понятное дело, что есть супервизиры, системд, роадранеры, свулы и т.д), но на node, go это из коробки и стабильно, а PHP для этого не предназначен. Я хоть и пишу на PHP, но отрицать, что у других ЯП, есть определенные преимущества перед ним, весьма сомнительно.
Это не проблематично, совершенно реально, делалось сотни раз, работает в проде и PHP прекрасно для такой задачи "предназначен", чтобы вы ни имели в виду.
Без всяких "супервизоров, роадраннеров и свулов".
поделитесь вариантом решения? если не секрет конечно(это не сарказм, не спор), просто интересно. Желательно, чтобы можно было мониторить состояние сервиса(жив, он мертв или завис) и удобно перезапускать его, при этом не бороться со всякими зомби процессами.
В комментарии поделиться не получится - места мало. Но в целом да, делали такое и не раз. Банально на тики, или чуть сложнее - на SIGALRM вешаем хэндлер, который в очень быстрое хранилище, например Redis, записывает идентификатор процесса и прогресс работы. Нет записи три секунды подряд - желтый статус, пять сек - красный.
ну как я понял, SIGNALRM дает возможность менее нагружать систему используя тики, если сравнивать в бесконечным циклом, но pcntl_alarm() вставляет паузы в обработку, что не для всех типов воркеров подходит(так как замедляет обработку) + " записывает идентификатор процесса и прогресс работы." - если я правильно понял, то это то-же доп. событие той-же кафки (я про свой пример), которое обрабатывается как штатное задание для воркера и добавляет в некий журнал и говорит нам, что обработчик работает(своего рода healthcheck), если записи нет, то значит у нас проблема.
>>> Есть некоторые вопросы:
1. Чем это решение(SIGALRM) принципиально лучше, того-же супервизора и любых +- подобных систем?
2. Пока что кажется, что данное решение оптимально для каких-то фоновых обработок, не требующих высокого уровня надежности и допускающих определенный простой в случае проблемы(например, синхронизация товаров с 1С, рассылка писем и еще что-то),
Допустим у меня система тестирования, которая работает на событиях от кафки (отдельный плеер от бекенда на react через веб-сокеты шлет сообщения на сервер Nodejs, далее данные пересылаются в журналы kafa, далее обработчик на PHP должен это все обработать и добавить записи в другой журнал кафки и все возвращается обратно в плеер)
Допустим 500 человек проходит тестирование и воркер завис, и все пропало почти(перезапустить тест нельзя, обратной связи никто не получит(и не должен, так как система подразумевает, что все должно работать в штатном режиме и с 1-го раза)
Для такой системы подобное решение не выглядит оптимальным, поправьте, если ошибаюсь...?
1. Чем это решение(SIGALRM) принципиально лучше, того-же супервизора и любых +- подобных систем? - по этому вопросу не много не так написал, не чем лучше супервизора и т.д, а для данного воркера его же в любом случае придется также запускать через супервизор, php script.php, системд и т.д, в чем отличие тогда - "Без всяких "супервизоров, роадраннеров и свулов". "
А как вам поможет супервизор в случае "залипания" процесса на какой-нибудь логической ошибке, вводящей его в бесконечный цикл? Процесс работает, живой. Супервизор не видит проблем, процесс не перезапускает.
Вам в любом случае для долгоживущих процессов нужен свой мониторинг их работы, основанный не на "работает/не работает", но на учете бизнес-логики таких процессов.
Живой пример - делали на таких "управляемых процессах" обработку прайс-листов. Десятков тысяч в сутки, на миллионы позиций каждый (если что - это торговля запчастями). Там естественной метрикой была строка прайс-листа. Пишем в редис раз в секунду инфу, на какой мы сейчас строке файла. Отличная метрика, позволяет сразу же понять, работает ли процесс так, как нам надо, или нет.
Ну и вторая принципиальная разница по сравнению с супервизором - когда вам нужен интерфейс мониторинга и управления процессами, которым сможет пользоваться вторая линия поддержки, вам супервизор не подойдет. Он не наглядный. А нам пришлось делать наглядную панель управления.
"А как вам поможет супервизор в случае "залипания" процесса на какой-нибудь логической ошибке " - судя по всему никак.
"Вам в любом случае для долгоживущих процессов нужен свой мониторинг их работы, основанный не на "работает/не работает", но на учете бизнес-логики таких процессов " - в своей системе по аналогии с вашей делал сквозное событие и проверку итогового значения, последнее событие должно пройти все инстанции(сокеты, кафку, обработчик и записать в таблицу), там уже смотрел, той-же кумой, что если время последней записи не более N минут, значит система жива.
Я не знаю, что тут называется «супервизором», но в эрланге supervision tree позволяет спокойно уронить процесс, если он не отвечает на сообщения, поэтому потенциальное «залипание» просто невозможно. И никакой мониторинг (кроме встроенного дерева супервизиров, но оно и так есть) — не нужен.
А как вам поможет супервизор в случае "залипания" процесса на какой-нибудь логической ошибке, вводящей его в бесконечный цикл?
Пишем [...] раз в секунду инфу
Если что, systemd такое умеет (WatchdogSec)
там речь была не про то, чтобы понять работает сам сервис или нет, в приле может быть ошибка и бизнес-логика перестанет работать как это задумывалось, а сам сервис будет работать дальше. Поэтому, далее и обсуждали варианты того, что должно быть что-то, что позволяет контролировать что свыполнением бизнес-логики все ОК, а не работой самого сервиса.
+ сам systemd (лично у меня, ну и от коллег слышал), часто плодит зомби процессы, при том что используются сигналы обработки
Нет, речь именно об этом: если бизнес-логика зависнет и перестанет слать watchdog-сигналы, systemd всё прибьёт
часто плодит зомби процессы
Чушь, такое возможно только при кривой настройке
systemd (лично у меня, ну и от коллег слышал), часто плодит зомби процессы, при том что используются сигналы обработки
И никто до сих пор не прислал патч с фиксом? Так не бывает. Если бы у меня так себя вела системная утилита, и я смог бы это поведение зафиксировать и воспроизвести — я бы сам прислал патч. И так бы сделали все более-менее профессиональные разработчики.
Запуск делается через менеджер процессов, тоже написанный на PHP. Он следит за тем, чтобы число активных процессов-воркеров не превышало заданный лимит, получает задание для каждого воркера, запускает его, пишет метрики - когда запущен, когда закончился, какой результат.
php ведь был "предназначен" для других целей - для простого и удобного создания динамичных html-страниц. И в этом качестве остаётся настолько удобным, что до сих пор его не могут выбить из этой ниши ни питон ни руби ни нода, не смотря на гигантское количество очень старого легаси.
Даже нода на первоначальном этапе использовалась похожим образом - она хостила какие-нибудь jade/pug страницы, рендерила из них на лету html. Но в таком качестве не особо прижилась. Основной смысл ноды - затащить на сервер JavaScript, поскольку JS невозможно изъять из фронтенда. Это изначально чисто организационное решение, которое позволяет шэрить кодовую базу (и программистов) хотя бы частично. Нода на этом пути далеко не первое решение, но самое известное (и на момент появления самое быстрое, потом появились и побыстрее).
Применение Ноды стало расширяться с появлением SPA приложений, когда применение JS на фронтенде увеличилось настолько, что по-сути исчез голый html. Использовать в этой связке php просто потеряло всякий практический смысл. Уж если тащить на сервер что-то другое, то что-то однозначно более мощное (Java, Go, может Rust).
Решения затыкать каждую дырку одним языком - Джава с Ваадином, Нода с pug/jade, php с fastCGI - они всегда будут, т.к. решают ОРГАНИЗАЦИОННЫЕ задачи - занять уже имеющихся специалистов. Так и надо эти технологии воспринимать - ну есть у вас php программисты, ну можно сделать и так.
Но пропагандировать им везде заменять другие языки - это лишнее, IMHO.
encoder := charmap.Windows1251.NewEncoder()
Не ожидал увидеть в новом коде в 2025 win1251. Почему не koi8? :)
Создатель Node.js Райан Даль в одном из своих интервью заявил, что для написания серверов предпочёл бы Go. ... Упомянутое интервью Даля состоялось в 2017 году
Вам не кажется, что это не лучший способ начинать статью? Ибо эта информация на грани манипуляции фактами. В 2018-ом году Даль релизнул Deno в качестве рантайма, вместо Node.js. И действительно, сначала он был написан на Go. Но потом знаете что произошло? Go был нещадно выпилен и заменён на, барабанная дробь, Rust! Я не являюсь сторонником раста, скорее нахожусь в оппозиции к нему... но факт очень показательный. Суть в том, что использовать слова Даля про Go несколько нерелевантно — вряд ли он до сих пор так считает, судя по развитию Deno.
Спасибо, я добавил это в статье.
Но тут нет манипуляции, т.к. слова Даля продолжают использовать как аргумент для противопоставления Го и Ноды - поэтому они приведены.Но я добавил упоминание Deno, чтобы смягчить формулировки.
Я не слышал его мнение о Rust применительно к серверам, возможно этот язык воспринимается скорее как системный, как и C на котором написана LibUV лежащая в основании Ноды.
Знаете, я полюбил Rust именно на стороне веб-серверов. Имел опыт переписывания нескольких из них с Java, NodeJS и Go на Rust и это было весьма увлекательно.
Был проект на Java. При переписывании на Rust 1-в-1 функционально под нагрузкой стал есть 200Мб вместо 3Gb оперативки. При этом обрабатывать в 4 раза больше запросов при в двое меньше CPU.
Был на NodeJS - вместо 2Gb стал есть 50Mb. Запросов почти в 10 раз стал больше обрабатывать.
Был Go - памяти стал есть в 2-2.5 меньше. Скорость выросла на 20%, CPU нужно меньше. Но, что занятно, скорость разработки даже увеличилась в команде в итоге. И никто из разработчиков не захотел обратно на Go.
Был на NodeJS - вместо 2Gb стал есть 50Mb. Запросов почти в 10 раз стал больше обрабатывать.
Это смотря что использовать на ноде, если NestJS и ORM, то да. там производительность нулевая. Если человеческие инструменты использовать, то всё очень даже хорошо, не предел совершенства, но очень даже ничего.
То же самое относится к Go, очень сильно зависит от того какие инструменты там используются.
Вот я сравнил GO и Node.js(его честь защищает Bun), на ситации из реальной жизни, жизненный цикл запроса:
- 3 запроса в базу данных
- сериализация в JSON
- десериализация JSON
Код того, чем занимает хэндлер на Go (драйвер для постгреса pgxpool
(иначе было бы все печально по перформансу))
Скрытый текст
rows, err := database.Query(context.Background(), "SELECT * FROM users LIMIT 100")
if err != nil {
log.Fatal("Query failed", err)
}
users := make([]User, 0, 100)
for rows.Next() {
u := User{}
err := rows.Scan(&u.Id, &u.Name, &u.Email, &u.Age, &u.Text, &u.Ser, &u.CreatedAt)
if err != nil {
log.Fatal(err)
}
users = append(users, u)
}
rows, err = database.Query(context.Background(), "SELECT * FROM users LIMIT 99")
if err != nil {
log.Fatal("Query failed", err)
}
for rows.Next() {
u := User{}
err := rows.Scan(&u.Id, &u.Name, &u.Email, &u.Age, &u.Text, &u.Ser, &u.CreatedAt)
if err != nil {
log.Fatal(err)
}
}
rows, err = database.Query(context.Background(), "SELECT * FROM users LIMIT 98")
if err != nil {
log.Fatal("Query failed", err)
}
for rows.Next() {
u := User{}
err := rows.Scan(&u.Id, &u.Name, &u.Email, &u.Age, &u.Text, &u.Ser, &u.CreatedAt)
if err != nil {
log.Fatal(err)
}
}
jsonStringify, err := json.Marshal(users)
if err != nil {
log.Fatal(err)
}
err = json.Unmarshal(jsonStringify, &users)
if err != nil {
log.Fatal(err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(jsonStringify)
Код того, чем занимает хэндлер на Node.js (драйвер для постгреса pg
)
Скрытый текст
const result = (await client.query(query1)).rows;
const result2 = (await client.query(query2)).rows;
const result3 = (await client.query(query3)).rows;
const jsonStr = JSON.stringify(result);
const parsedJson = JSON.parse(jsonStr);
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(jsonStr);
Где query1,query2,query3 это
Скрытый текст
const query1 = {
// give the query a unique name
name: 'fetch-user1',
text: 'SELECT * FROM users LIMIT 100',
values: [],
}
const query2 = {
// give the query a unique name
name: 'fetch-user2',
text: 'SELECT * FROM users LIMIT 99',
values: [],
}
const query3 = {
// give the query a unique name
name: 'fetch-user3',
text: 'SELECT * FROM users LIMIT 98',
values: [],
}
Т.к. pgxpool в Go делает все запросы по умолчанию prepared statements, а pg в ноде нет, то чтобы сравнение было честным в ноде я тоже сделал чтобы они были prepared statements.
Результаты для Go:

Результаты для Node.js (в лице Bun)

Получается 9к RPS против 7k RPS, выходит что в среднем при условии что проект там и там пишет адекват, Go быстрее чем Node в среднем на 23%. А значит исходя из вашей математики, если Rust быстрее go на 20%, то Rust быстрее Node именно в задачах rest api, в среднем на 36%.
Но с точки зрения потребления памяти да, нода жрет конечно больше, не так что прям критично и в современных реалиях это не проблема.
Но справедливости ради:
- Львиную долю в проигрыше Node занимает драйвер pg, как бы можно куда быстрее сделать реализацию. И это я молчу про то, что в ноду можно портировать из C++ или rust драйвер для постреса и вот тогда совсем другой колин кор будет)
- В Go тоже pgx это не предел, я написал свой драйвер для постгреса и RPS в среднем на 20-25% больше если pgx заменить на мой.
Вы совершенно правы. Но если бы сервисы которые пришлось переписывать были написаны адекватными специалистами, то их и не пришлось бы переписывать.
NodeJS и Go и Rust и другие - все хорошие инструменты, когда применяются адекватно и по делу.
У меня больше притензии бывают не к самому языку, а к тулингу вокруг него. Но это влияет на производительность разработки, не скорости исполнения, конечно.
Но если бы сервисы которые пришлось переписывать были написаны адекватными специалистами, то их и не пришлось бы переписывать.
Это, в точку. Жаль только имеем то, что имеем(
У меня больше притензии бывают не к самому языку, а к тулингу вокруг него.
Ну вот да, допустим зачем nestjs в ноде, если есть express и fastify? Он приносит ноль пользы, добавляет кучу проблем и говнокода, ставит на колени производительность. И вот как бы заем использовать этот шлак? Я вот хоть убей не понимаю.
Rust меня подкупает тем что да, он очень быстрый все дела, и без рантайма, но вот синтаксис у него специфический и например для разработки rest api вот вообще никак я не могу его использовать.
В Go вообще на раз два можно убить производительность просто тупо одним не верным решением, и получается ты заплатил большой многословностью, но в итоге не выиграл в перформансе, или если выиграл, то гроши не принципиальные по сравнению с тем, что заплатил, а это обида) Элементарно я поднял на 20% производительность просто тупо за счет того, что написал свой драйвер для работы с pg, если победить в Go json encode/decode, эти операции можно легко в разы ускорить, Rust тому подтверждению, да даже PHP в разы быстрее JSON encode/decode делает. В общем, так то если Go ещё довести до ума чтобы он не обсирался на абсурдных вещах, и reflect
сделать нормальным, чтобы на этапе компиляции инфа о типе, полях и т.п. зашивалась в объект, а не уничтожала производительность в рантайме, то будет уже прорыв. А если ещё ошибки будут сами по умолчание на верх улетать, и не нужно будет писать бесконечные if err != nuil
после каждой строчке, то будет прорыв для языка в квадрате)
... Rust меня подкупает тем что да, он очень быстрый все дела, и без рантайма, но вот синтаксис у него специфический ...
Тоже по началу не понимал его, а потом как понял!..
В итоге мне этого синтаксиса не хватает теперь в других языках :)
А если серьезно, то, к примеру, когда читаешь код на Java или Python - то из того, что видишь на экране не понятно - заработает ли оно в многопотоке, что там с типами, что там с Null Pointer Exception и вообще с Exception и т.д. Чтобы это понять нужно перешерстить кучу кода и, бывает, заглянуть ещё и в код сторонних библиотек.
В Rust же, ты видишь код и сразу понимаешь - поддерживает он много-поток или нет, что там с типами, с ошибками, с Null типами и т.д.
В итоге код читается гораздо быстрее.
Просто по моей специфике работы мне приходится переколбашивать тонны чужого кода чтобы его выправить. И вот код на Rust в этом плане куда как приятнее и понятнее.
Но по началу да, отталкивает.
В Rust же, ты видишь код и сразу понимаешь — поддерживает он много-поток или нет
А в эрланге даже не видя код, точно знаешь: поддерживает, и не только многопоточность, но и кластеризацию.
Это любопытно, честно говоря, пока не встречал суждений про Rust в качестве серверного языка. Нужно провентилировать вопрос.
Вроде читал, что Bun на Zig еще быстрее, чем nodejs, deno.
Bun на Zig:
https://github.com/oven-sh/bun/issues
Посмотрите сколько там crash-issue заведено и сколько вы таких найдете у Deno?
А у Deno есть такая же удобная система репортов как bun.report?
Конечно:
https://github.com/denoland/deno/issues
Также можете посмотреть Issue Tracker'ы других популярных проектов на Zig и на Rust. Zig интересный язык с хорошим потенциалом, но, к сожалению он точно также позволяет легко отстреливать себе пальцы. Что и происходит, к сожалению, в крупных проектах на нем.
Процесс на Ноде занимает существенно больше оперативки
А зачем тупому круду занимать память. Это простите за сравнение, тоже же самое, что GUI на электрон.
На Go пишется много микросервисов. И если у тебя 1000 инстансов, то NodeJS не самый лучший выбор. И кмк NodeJS не про хайлоад. NodeJS это про чтонибудь простенькое. Так как если начнется развитие логики, куча лапши на JS убьет развитие. На помощь тут идет TS. Но, оверхед, что это JS все равно остается.
Так что ниша node - что то простое и небыстрое.
Не совсем, на ноде прекрасно себя чувствуют большие проекты. А вот про не быстрое это да. Но скорость в реальности это тоже очень редкий кейс для бэкэнда. В большинстве бизнес приложений узким местом является БД. И по совокупности факторов у ноды очень много преимуществ. TypeScript высокоуровннвый язык и имеет много плюсов в плане времени разработки и при этом обладает типизацией что не типично для интерпритируемых языков но дает огромные плюсы в плане поддержки. Кроме того большинство разработчиков в вебе в какой то степени с ним знакомы. С точки зрения бизнеса на текущий момент, вряд ли какой либо язык обладает таким набором приемуществ. Поэтому на текущий момент, нода это мейнстрим. А вот для Go все очень туманно для хайлоада пришел Rust для скорости разработки Нода. Мне очень нравится Го как язык но к сожалению на мой взгляд для него просто нет места на рынке. Go очень дорогой не супер быстрый, количнство проектов не так велико, кроме того что он приятный в плане читаемости кода больше нечего выделить.
В большинстве бизнес приложений узким местом является БД. И по совокупности факторов у ноды очень много преимуществ
В лютом энтерпрайзе это не совсем правда. И производительность бека важна и зависит не только от БД. Здесь приходится обмазываться security check на каждый чих, аудит, расширенные логи, трейсы, метрики, контроль идемпотентности, circuit breaker'ы, контроль гарантированной доставки сообщений и прочее безобразие.
И всё это ест CPU и память на каждый запрос. Поэтому вопрос производительности самого языка и фреймворка тоже важно.
Так что ниша node - что то простое и небыстрое.
Ну вообще то, если говорить про адекватов, то очень даже быстрое и способное легко держать тысячи RPS, особенно если запускать через Bun, это бесплатно +20% производительности. И опять же можно далеко не простое, а очень больше и сложное, тоже изи. А вот если говорить про nestjs + orm, то да, там вообще производительность на коленях. Это скажем так позор языка.
Если взять Bun, где еще все быстрее и тоже не нужно настраивать среды... Самый большой плюс это единая среда для клиента и сервера с возможностью общего кода.
Если вам нужен быстрый, параллелизуемый, отказоустойчивый WebAPI сервер — очень странно сравнивать ноду с го и не сравнивать с эликсиром. Там даже финикс не нужен, достаточно простого Plug.
Решение будет короче, чем на ноде и не менее эффективно, в сравнении с го (внезапно). Я как-то баловался с config-first фреймворком для внутреннего API (без авторизации, но прикрутить ее можно за 30 минут), получилась вот такая библиотека — с временем отклика в десятки микросекунд на миллионе предзагруженных (в эрланге не принято ходить в базу на каждый чих) джейсонов.
Больно это экзотичный вариант с BEAM. Сравнение между го и нодой сам Даль создал. Его фраза про Го известная, что он там потом делал не все помнят
Что значит «экзотичный»? Мне лично нужна всего одна работа, и у меня есть всего одна жизнь, поэтому я пишу на эликсире и эрланге, и ни за какие деньги не пойду в го или ноду.
Даль не создавал сравнения между го и нодой. Он создавал сравнение между дено и нодой, или между го и джаваскриптом. Потом он открыл для себя раст. Есть такие люди, которым нужно раз в несколько лет «разрушить старый мир до основания, а затем». Смысл? Высококонкурентный нагруженный кластер все равно не создать без боли ни на ноде, ни на дено (кластер, а не сотню серверов за балансером).
Экзотичный, это значит что мне удалось найти на него 11 вакансий на известном сайте против двух тысяч на Джаву.
Но вы не думайте, что я не люблю Эрланг - это очень интересный практичный язык, я с удовольствием смотрел лекции Джо (Лесли) Армстронга. Я пользовался продукцией эрливидео. Если на нём есть стабильная работа, то я понимаю, почему она может нравится. Паттерн мэтчинг, отсутствие привычных конструкций - всё выглядит очень "вкусно". У меня даже создаётся впечатление, что горутины это идея инспирированная удачным применением "легковесных процессов" в BEAM
Node по любому проиграет Go, и если про исключения, то и в Go они уже есть только называются по другому. Решили немного переделать\. называются только не Exceptions, а уж PHP тут вообще отдыхает, потребление памяти что Noda, что PHP, это рядом не лежали
Какое нафиг потребление памяти в WebAPI? Там вся нагрузка на базе, и на сериализаторе. Память узким местом там в принципе не станет никогда, поэтому этот аргумент вообще не аргумент. Ну [допустим] меньше, и чё?
называются только не Exceptions
А как? Просветите уж.
Node по любому проиграет Go
Вообще не всегда, и при адекватных подходах и там и там, вопрос на сколько? Ответ я знаю) В среднем на 25-30% будет быстрее Go, но это из-за того что в ноде драйвер pg так себе по скорости, прям очень слабоват. А теперь другой вопрос, насколько быстрее и удобнее разработка на ноде?) Насколько система типов в Typescript круче чем в Go?) А ещё, если в Go не использовать самые быстрее подходы и инструменты, то он уже будет проигрывать ноде. Так что да, Go может быть быстрее ноды, но при определенных условиях и там и там, а может быть и наоборот и медленнее.
Посмотрите https://habr.com/ru/articles/890882/#comment_28042698
А что насчет Python? Он же тоже вроде как популярен на бэкенде?
А что насчет Python? Он же тоже вроде как популярен на бэкенде?
Он очень медленный, а по сравнению с node.js даёт ноль преимуществ в скорости и удобстве разработки, поэтому нет смысла за просто так получать низкую производительность. Но это не отменяет того факта, что люди плюют на производительность и берут его всё равно, это да.
На текущий момент python в основном это для обучения и небольших скриптов, писать на нем крупные апи бизнесовых приложений не лучшая идея, не то что бы нельзя просто премуществ нет, одни недостатки.
Где хоть он "популярен"? В статьях на хабре? ))
Сравниваем-сравниваем, и старательно делаем вид, что Java не существует... :)
Java для простого WebAPI сервера? Может быть, кобол?
А что, Java "слишком сложная", чтобы на ней писать "простые сервера"?
Java — самый простой язык, из более, чем десятка, с которыми мне доводилось вплотную работать, и из более 20, на которых я смогу за пару дней написать простой сервер.
Но вот развернуть это всё благолепие через CI/CD в прод — слишком уж много никому не нужных плясок вокруг ничего. Да и ресурсов оно сожрёт непомерно много для простого микросервиса.
Это сравнение инспирировано исключительно фразой создателя Ноды и несколькими статьями описывающими именно такой переход. Здесь нет Джавы и питона только по этой причине, а не потому что они не пригодны для серверов. Как раз наоборот мне было бы любопытно написать одинаковые сервера на Node, Java, Go и сравнить. Думаю писать на Джаве (Спринге) концептуально меньше, только постоянная декларация типов увеличит количество букв. И память, кажется, будет жрать не меньше ноды. Но это предположение
Переходим с Node.js на Go… но это не точно