Всем привет! На этой неделе мы поговорим с вами о программной платформе Node.js, познакомимся с ее архитектурой и узнаем, какие возможности она нам предлагает. Вообще появление этой платформы в значительной степени способствовало выходу языка JavaScript за рамки использования его в браузерах и позволило разработчикам писать приложения на стороне сервера. Например, при помощи этой программной платформы можно было написать обычный веб-сервер. Для того чтобы перейти к ознакомлению с этой платформой, для начала нам необходимо разобраться с предпосылками ее появления. И в этом видео я расскажу вам о типичных операциях, которые необходимы для работы веб-сервера. Мы узнаем, что большая часть этих операций взаимодействует с системами ввода-вывода, а также затронем тему блокирующего ввода-вывода и поймем, как ограничение блокирующего ввода-вывода повлияло на появление этой программной платформы. Начнем мы немножечко издалека и поговорим о ресурсах. Любая программа потребляет те или иные виды ресурсов в том или ином объеме. Например, если ваша программа выполняет какие-то сложные вычисления, она в значительной степени потребляет время центрального процессора. Возможно, она хочет хранить какие-то промежуточные вычисления в оперативной памяти, таким образом потребляя и этот ресурс. А, может быть, для вычислений необходимо считать какой-то массив данных с диска или, например, с удаленного хранилища. В этом случае она обращается к системам ввода-вывода для чтения с локального диска или для обращения по сети. Для примера рассмотрим вначале сферические операции в вакууме. Например, вычисления числа Фибоначчи. Эта операция, в основном, потребляет время центрального процессора. Мы можем сказать, что она ограничена производительностью этого процессора, и если мы поставим процессор мощнее, мы сможем вычислить это число быстрее. Второй пример: подсчет количества строк в файле. Здесь уже не так много вычислений, нужно лишь увеличивать счетчик. И большую часть времени данная операция будет потреблять ресурсы систем ввода-вывода, ведь файл необходимо вначале прочитать, прежде чем подсчитать количество строк в нем. Но обратимся к более реальному примеру, а именно посмотрим на основные операции, из которых состоит работа веб-сервера. Для начала нам необходимо прочитать запрос от пользователя. Безусловно, это операция, которая потребляет ресурсы системы ввода-вывода, так как связана с сетевым взаимодействием. Далее, получив запрос, мы должны его разобрать. Это, в основном, вычисления, и здесь мы потребляем время центрального процессора. Возможно, для подготовки ответа для пользователя нам необходимо сходить в базу данных или сделать запрос какому-то удаленному API, другому серверу. Обе этих операции опять потребляют у нас, в основном, ресурсы системы ввода-вывода, и чем производительнее эти системы, тем быстрее эти операции выполнятся. Далее мы на основе этих данных генерируем HTML, здесь опять вычисления. И отправляем этот полученный HTML пользователю. Опять ввод-вывод. Как мы видим, в работе веб-сервера достаточно много операций, взаимодействующих с системами ввода-вывода. И именно оптимизация данных операций позволит в значительной степени увеличить производительность нашего веб-сервера. Наш веб-сервер запускается операционной системой в потоке. В рамках одного потока может выполняться одновременно только одна операция, независимо от того, вычислительная она, или, например, мы читаем файл с диска. Для обращения к системам ввода-вывода приложение активно взаимодействует с операционной системой. И по умолчанию данное взаимодействие — блокирующее. Что это значит? Например, мы обслуживаем первого пользователя, выполняем какие-то вычисления, и для ответа нам понадобилось сходить, прочитать какие-то данные из локального файла. Мы делаем запрос в операционную систему и начинаем ждать данные из этого файла. Так как ввод-вывод у нас блокирующий, на это время наше приложение замирает и не может больше выполнять никаких операций. В этот самый момент к нам может прийти второй пользователь, и мы не сможем его обслужить, до тех пор пока не вернутся данные из файла для первого пользователя, и только тогда мы сможем ответить и первому, и второму пользователю. Таким образом, мы для каждой операции ввода-вывода блокируем поток выполнения нашей программы. Блокирующий ввод-вывод может накладывать существенные ограничения на производительность нашего веб-сервера. Допустим, мы читаем 1 Кб данных с твердотельного накопителя. Это занимает всего 0,0014 миллисекунды. Казалось бы, совсем немного времени! Но за это время стандартное ядро двухгигагерцового процессора позволяет выполнить 28 тысяч циклов, то есть примерно 28 тысяч операций — выполнить кучу полезной работы. Но пока мы ждем этот килобайт данных, наш поток приложения блокируется, мы простаиваем и не можем выполнить эти 28 тысяч циклов, для того чтобы сделать полезную работу. Пример становится еще более ярким, если мы посмотрим на сетевые взаимодействия. Только для установки сетевого соединения необходимо 60 миллисекунд. За это время процессор выполнит уже 132 миллиона циклов, или 132 миллиона операций. Это просто куча полезной работы! В этом видео мы с вами познакомились с разными типами операций и посмотрели, какие ресурсы они потребляют. Выяснили, что веб-сервер, в основном, состоит из операций, которые потребляют ресурсы ввода-вывода. И если мы используем блокирующий ввод-вывод, то большую часть времени наш веб-сервер будет простаивать, не выполняя никакой полезной работы.