Заканчиваю курс по ноде и хотел детальнее понять работу данной платформы. В предоставленном курсе было оговорено, что сам Javascript синхронный язык, но Node.js API(файловой системы, интернет запросов), которые мы можем подключать и с помощью транслятора, который привязывает вызов Javascript функций в C++ вызовы, использовать библиотеку libuv, которая написана на плюсах и использует многопоточность, и также асинхронна.
Есть движок V8 -> API Node.js (http, fs, path) -> Node.js Bindings-> Libuv(c++, asynchronous i/o, multi-thread).
Node.js просто передает запрос в Libuv, чтобы та выполнила задачу обратившись к операционной системе и будет уведомлена, когда задача будет выполнена, при всем этом процессе Node.js работает дальше по принятию запросов. Платформа работает как менеджер, дегелировав всю работу библиотеке Libuv и операционной системе, которую не выполняет сразу в Javascript.
В самом Libuv есть EventLoop, он обрабатывает все запросы входящие как события и регистрирует для каждого коллбэк функцию, которая после того как будет сигнал о завершении выполнится и отдаст результат конечной машине.
Если это задача общения с сервером по интернету, то она выполняется напрямую в операционной системе, а другие задачи например считывание файла выполняются в Thread Pool. В самой Libuv есть группа потоков. Один поток исполняет V8 движок и EventLoop, и также ряд потоков(4 по дефолту), каждый который может выполнять одну задачу в одно время. Но где это возможно, то запросы выполняются напрямую операционной системой, вместо выполнения их через поток, так как это требует чуть больше ресурсов на управление. Выделенное жирным определение относится напрямую к вопросу
Сами события делятся на Event Loop Phases: Timers -> I/O callbacks -> setImmediate -> Close callbacks и выполняются в таком порядке.
Также мы можем использовать кластеры или пакет pm2, который устроен на этой идеи и на заданом количестве ядер процессора развернуть nodejs экземпляр для обработки запросов. Так как если у нас один экземпляр, то при сложных криптографических, сортировок и работы со сложными обьектами при преобрзаованиях JSON могут блокировать EventLoop и сервер примет следующий запрос на другом экземпляре.
Я написал общий пересказ усвоенной информации возможно где-то неправильно. Вопрос к потокам и процессам, их определения и связь с ресурсами компьютера. Если взять php, то там на каждый запрос создается свой процесс и ими управляет apache, минус подхода, что этим всем надо управлять, соответственно нужны дополнительно ресурсы компьютера. Я конечно понимаю, что это не минусы и не плюсы, всё зависит от задачи, от навыков разработчика и т.д
Но если мы остановимся на nodejs, что по сути среда выполнения js кода на стороне сервера и в качестве дополнительных инструментов можем Nginx навесить поверх, то обьясните мне детальнее насчет thread pool в самой ноде и роли ядер процессора.
Допустим у нас 4 ядра логических и физических. На каждому ядре развернуто с помощью pm2 пакета экземпляр ноды.
Каждый экземпляр это реалтайм исполнитель Javascript языка и возможностью подключать модули, которые добавят функционал для работы с файлами, запросами и т.д по средствам обращеня к Libuv библиотеке.
Thread pool - я его представляю как стэк операций, функций, которые независимы от друг друга и используют возможность процессора для непосредственного обсчета или делегирование работы жесткому диску, сетевой карте и т.д.
1. Каждый thread может выделяться на одном ядре, то есть на одном ядре выполняется движок V8 и дополнительно выделены потоки под задачи асинхронные?
Я просто думал, что как раз дополнительные потоки должны выделяться на других логических, физических ядрах.
Когда на одном ядре запущен Node.js, а библиотека Libuv сама уже при необходимости создает потоки по средствам системных обращений к свободным ядрам.
2. Или если мы выделяем экземпляр Node.js на каждый прцоессор, то thread pool в принципе нету и всё выполняется по очереди не асинхронно.
nodejs идеологически однопоточный, то что внутри у него могут быть потоки, это для реализации асинхронного поведения заведомо синхронных вещей...
после 10.5 версии были добавлены worker_threads гре разработчик может создавать настоящие треды, но для доступа к данным из соседних потоков нужно использовать соответствующие типы данных, например слать сообщения или создавать SharedArrayBuffer...
p.s. так как адекватных структур данных для многопоточного доступа в nodejs не завезли, то вся работа покроется кучей лишнего кода для реализации недостающего функционала, поэтому если это так критично, лучше реализовывать важные места на более адекватных языках программирования
А для какого рода проектах нужно управление потоками и доступа к соседним? Я начал, вначале с ларавела, потом решил перейти на реакт и ноду. Не скажу, что сильно ощущаю разницу, по сути оба однопоточны. Реализация эвентлупа, libuv скрыта, хотя общее поимание необходимо, поэтому и задал вопрос. Но всё это детский сайд от реального программирования, пока что отталкиваюсь от чего то.
KIQIK, как минимум как только начнешь упираться по производительности в возможности железа, а это очень быстро произойдет с ростом количества клиентов (или данных, смотря что там за задачи)
Рано или поздно, при работе с данными наступит момент, когда либо самому придется заниматься многопоточной реализацией (не важно треды или процессы, все упирается в данные и параллельный доступ к ним), либо взять готовую реализацию, но в этом случае твоя задача уже должна быть кем то реализована
Правильная низкоуровневая реализация многопоточного доступа к памяти дает повышение производительности чуть ли не на порядок, по сравнению с универсальными решениями, а когда оперативной памяти стало действительно много, это снова стало актуально (хотя люди по старинке топают к приложениям баз данных в т.ч. in memory, тратя кучу времени на сериализацию и памяти на оверхед, точно помню как человек не мог на сотнях гб оперативке решать свою задачу, сторонними базами данных, не влезало, когда как своя структура в памяти заняла бы от силы 80гб)
rPman, Я понимаю на примитивном уровне, что что пхп или нода больше подходит для небольших и средних проектов, для прототипов, стартапов, чтобы быстро развернуть или под конкретные задачи, где есть преимущества цены, поиска специалистов и т.д.
Крупные проекты на долгой перспективе, где важна производительность с связи с большими обьемами, нагрузкой реализуются в большей степени на каком стеке? Хотя это конечно и зависит от архитектуры, на микросервисах можно же различные части приложения на разных языках писать.
Но просто в целом, куда для общего понимания помимо верстки, ноды, реакта посмотреть в сторону бэкэнда, оптимизации? Не скажу, что собираюсь всё выучить и понимать, но в пределах понимания мне кажется любому человеку надо понимать принцип. Во всяком случае надо пробовать и смотреть, что ближе тебе..
KIQIK, в подавляющем большинстве случаев крупные проекты переростают из 'небольших и средних проектов, для прототипов, стартапов', которые в свою очередь реализуются на 'пхп или нода больше подходит для'
и проблемы решают по мере их появления, переписывая критичные куски на чем то адекватном
p.s. правильно писать изначально опасно дорого, т.е. можно не доделать до конца свой стартап и он в принципе не появится
такова селяви
иногда, если изначально грамотно составить архитектуру проекта, наверное можно подстелить соломку на будщее и не сильно на это потратиться
rPman, Ну да, так тоже верно, что заранее все предугадать нельзя, это очень частные случаи. Ладно, спасибо за ответы, там уже когда устроюсь видно будет что и как.
по первому вопросу, нода запускается с 1 тредом отвечающим за ЭЛ. Да все задачи выполняются из очереди последовательно и та часть задач, которые требуют системных вызовов передается на исполнение в пулл уже инициализированных тредов так же через очередь, отмечу что число тредов либЮВ можно менять, согласно документации есть соответствующие ключи при запуске. Этот механизм позволяет экономить время и ресурсы на постоянную инициализацию тредов и тем самым достигается эффективность использования существующих тредов.
На счет монопольности треда на процессор это в любом случае иллюзия, помимо процесса запущенного в ноде в системе есть еще сотни процессов чего-то еще.
по второму процессу, кластеризация по числу ядер в целом считается оптимальной, в виду того что при большем числе экземпляров процесса будет переключение между ними, что влечет к дополнительным расходам на исполнение приложения.
если сравнивать с пхп и тем что каждый запрос это новый тред, то плюсы ноды в том, что нет задержек на инициализацию и закрытие треда, нет избыточной конкуренции тредов, есть максимально возможное использование каждого потока через системы очередей.
Из минусов, ресурсов ядер может не хватать и очередь будет расти, тогда кластеризация уже будет требовать распределения нагрузки по числу машин в горизонтали.
Спасибо, не знаю почему при просмотре материала забыл, что помимо ноды есть ещё много сервисов операционной системы, которые работают независимо от всего остального работают. А если говорить в целом про потоки и запущенные процессы, это огваривается в рамках языков с многопоточностью или работы операционной системы и как она может выделять ресурсы процессора на это? По каким запросам лучше прочитать по этой теме.
Я с++ первым языком выучил, но почти сразу ушел на веб, поэтому только азы: массивы, обьекты, указатели выучил, с потоками не работал. Если в ноде работа с файлами, сетевыми запросами передается в вызовы соответствующие в libuv, то в php как реализован данный подход? Там в самом языке вшиты низкоуровневые запросы к системе, а вместо libuv сервер апачи занимается обработкой запрос с последующим менджментом потоков и выполнения в них скриптов?
С архитектурой языков, операционных систем не знаком, хотя это расширяет кругозор безусловно. Если можно, то в кратце опишите основные тезисы.