Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Веб-сервер Python: Веб-разработка (Flask)

Процессы

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

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

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

Process List

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

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

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

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

Веб-сервер

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

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

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

WSGI

У CGI-серверов был один важный недостаток — они запускали скрипты на каждый запрос, а значит каждый раз запускался интерпретатор. В ответ CGI в Python-коммьюнити предложили новый стандарт, описанный в PEP3333 — WSGI (Web Server Gateway Interface). Основная идея WSGI (читается как WIZ-ghee) в простом взаимодействии Python-приложения и веб-сервера. Согласно стандарту веб-приложение это просто функция (или другой callable объект), которая принимает два аргумента: словарь переменных окружения и функцию, устанавливающую параметры ответа, а возвращает iterable в качестве ответа. Минимальное WSGI-приложение, то есть приложение поддерживающее стандарт WSGI, выглядит примерно так:

def app(environ, start_response):
    data = b"Hello, World!\n"
    start_response("200 OK", [
        ("Content-Type", "text/plain"),
        ("Content-Length", str(len(data)))
    ])
    return iter([data])

WSGI сервер внутри себя вызовет нашу функцию app и с помощью механизма замыканий передаст в нее необходимые аргументы. Все, что касается конкретного запроса, приходит в аргументе environ, функция start_response() устанавливает параметры ответа (в данном примере, размер ответа и тип содержимого), а затем функция просто возвращает итератор, построчно отдающий ответ. Все современные веб-фреймворки в Python поддерживают стандарт WSGI, то есть предоставляют на верхнем уровне этот callable объект (app в Flask, wsgi модуль в Django), а все WSGI-серверы умеют с этим объектом работать. Некоторые веб-серверы, как nginx, не поддерживают стандарт, но все равно умеют "общаться" с WSGI совместимыми (gunicorn, uWSGI), поэтому вы часто будете встречать классическую связку как nginx-gunicorn-Django.

Реализации

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


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

Сохраните код WSGI-приложения из урока в модуль example.py. Установите gunicorn. Всегда все устанавливайте в виртуальное окружение. Создать его можете любыми инструментами. Запустите модуль командой gunicorn -w 4 example:app — этой командой мы запускаем WSGI-сервер gunicorn и указываем ему путь до нашей функции-приложения. Перейдите в браузер по адресу в выводе и посмотрите на результат.


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

  1. Сетевые сокеты
  2. CGI
  3. WSGI

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Python-разработчик
Профессия
с нуля
Разработка веб-приложений на Django
1 декабря 10 месяцев

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и соглашаетесь с «Условиями использования»