Зарегистрируйтесь, чтобы продолжить обучение

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

В этом уроке мы рассмотрим, для чего нужен веб-сервер, и как устроено сетевое взаимодействие.

Процессы

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

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

Внутри себя процесс может делиться на потоки:

Process List

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

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

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

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

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

Благодаря DNS браузер получает IP-адрес компьютера, на котором расположен сайт указанного домена. Также существует соглашение, согласно которому веб-сервер, обслуживающий сайт по протоколу 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 — простое взаимодействие 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