Процессы

Давайте теперь посмотрим, для чего нужен веб-сервер. Ответ на этот вопрос требует небольшой подготовки.

Единицей исполнения в операционных системах является процесс. Это некоторая абстракция внутри ОС (имеется в виду, что процесс невозможно представить визуально). Любая запущенная программа представляет собой либо один процесс, либо набор процессов. Например, в браузерах одна вкладка, как правило, — это один процесс. Особенность процессов в том, что они изолированы друг от друга. Например, сбой в одном процессе не влечёт за собой остановку работы других. Такое свойство процессов можно наблюдать в тех ситуациях, когда одна из вкладок браузера начинает тормозить и в конце концов зависает (и её не всегда удаётся закрыть!). В это время можно без проблем продолжать использовать другие вкладки.

Внутри себя процесс может делиться на потоки, но эта деталь не влияет на описываемую тему, поэтому я её опускаю. Подробнее о менеджменте процессов можно прочитать в книгах по операционным системам.

Process
List

Посмотреть список процессов в Linux можно командой ps aux либо top

Понимание процессов тесно связано с сетевым взаимодействием. Взаимодействие между двумя компьютерами в сети — всегда сводится к взаимодействию двух процессов. Другими словами, нельзя взять и подключиться к компьютеру в целом — можно подключиться только к конкретному процессу конкретной программы. Происходит это так: одна программа, которая хочет, чтобы к ней можно было подключаться по сети, при запуске начинает слушать сетевой сокет. Такая программа называется сервером. Другая программа к ней подключается. Такая программа называется клиентом. В случае веба, сервер — это конкретный веб-сервер, например, nginx, а клиент — это браузер.

Здесь нужно сделать небольшую ремарку насчёт "слушать сетевой сокет". Сетевое взаимодействие между программами двух компьютеров осуществляется с помощью протокола TCP, поверх которого уже работает HTTP. Для обращения к другому компьютеру нужно знать два параметра: IP-адрес и порт. Так вот "слушать сетевой сокет" означает занять определённый порт (на определённом сетевом интерфейсе) и дать возможность обращаться к процессу через него. Именно по номеру порта операционная система понимает, к какому процессу пытаются обратиться.

Браузер, благодаря DNS, получает IP-адрес компьютера, на котором расположен сайт указанного домена (например, google.com). А вот откуда он знает порт, на котором висит веб-сервер в ожидании входящих запросов? Ответ на этот вопрос очень простой: существует соглашение, согласно которому веб-сервер, обслуживающий сайт по протоколу HTTP, слушает порт 80, а протокол HTTPS обслуживается на порту 443. Но так бывает не всегда. Во время локальной разработки обычно используются другие порты, например, 3000, или 4000. Сам номер не принципиален, главное, что он доступен для веб-сервера, и вы обращаетесь через браузер именно к нему. Порт указывается через двоеточие после названия сайта, например www.google.com:80.

Client-Server

Веб-сервер

Веб-сервер — специализированная программа для обслуживания сайтов. Один веб-сервер может обрабатывать практически любое число сайтов (Virtual Hosts в HTTP). В общем случае он перенаправляет входящие сетевые запросы на код сайтов, получает от них ответ и возвращает его браузеру. Кроме главной функции, у веб-серверов огромное число вспомогательных. Среди них кеширование, перезапись запросов, раздача статики (например, картинки), reverse proxy, балансировка нагрузки и многое другое. Веб-сервера ничего не знают про то, на чём написан сайт. Все способы взаимодействия веб-сервера и сайта на любом языке стандартизированы. Благодаря этому веб-серверов существует не так много, и все они могут работать с сайтами, написанными на чём угодно.

Первым и самым простым способом взаимодействия веб-сервера с сайтом был CGI (Common Gateway Interface). Этот стандарт сразу разрабатывался с учётом того, что сервер не должен зависеть от того, на чём написан сайт. Он основан на переменных окружения. По сути, сайт представляет из себя исполняемый файл, который запускается веб-сервером во время обработки входящего запроса и передаёт в него все параметры запроса через переменные окружения. Всё, что требуется от скрипта, — это вернуть HTTP-ответ в стандартный вывод (STDOUT). Общий алгоритм работы выглядит так:

  1. Клиент запрашивает страницу сайта.
  2. Веб-сервер принимает запрос и устанавливает переменные окружения (через них приложению передаются данные и служебная информация).
  3. Веб-сервер перенаправляет запросы через стандартный поток ввода (stdin) на вход вызываемой программы.
  4. CGI-приложение выполняет все необходимые операции и формирует результаты в виде HTML.
  5. Сформированный гипертекст возвращается веб-серверу через стандартный поток вывода (stdout). Сообщения об ошибках передаются через поток ошибок (stderr).
  6. Веб-сервер передаёт результаты запроса клиенту.

CGI

Очень важно осознать, что в режиме CGI, скрипт, который представляет из себя сайт (как программу), запускается на каждый запрос заново. Это значит, что вся логика инициализации отрабатывает для каждого запроса по новой, а после выполнения запроса, ничего не остаётся (скрипт просто завершается). Если между запросами есть некоторое состояние (например, пользователь что-то сохранил), то его нужно отправлять в какое-то хранилище, файловую систему (создать файл) или базу данных.

Реализации

Разных веб-серверов довольно много. Начиная от встроенного в сам PHP, с которым мы познакомимся очень скоро, заканчивая веб-серверами общего назначения, которые используются всеми. Самым популярным и эффективным решением на текущий момент является nginx. Именно с ним и стоит познакомиться. Для разработки он не понадобится, так как в PHP встроен свой сервер, но в продакшен-среде без него никак. Кроме него набирает популярность веб-сервер Caddy, который хоть и не такой быстрый, но обладает рядом важных особенностей, он значительно проще в настройке, из коробки умеет генерировать сертификаты и многое другое.

Кроме указанных серверов, в PHP мире до сих пор пользуется популярностью Apache. Этот веб-сервер когда-то был передовым решением, но те времена давно ушли. Использовать Apache можно только в том случае, если у вас нет выбора, например, на хостинге предлагают именно его. Во всех остальных ситуациях предпочтительнее nginx. Связано это с моделью работы самого сервера. Apache работает по модели "поток за запрос", что значительно более затратно и медленно по сравнению с асинхронной моделью nginx.

Самостоятельная работа

Установите nginx и убедитесь в том, что он запускается и работает. Сделать это можно по одному из руководств в сети, которые гуглятся так: php nginx <имя вашей операционной системы>. Это задание повышенной сложности. Если не получается прямо сейчас, то не тратьте время, сначала пройдите курс, а затем попробуйте ещё раз.


Дополнительные материалы

  1. Сетевые сокеты
  2. CGI
  3. FastCGI
Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →