1 of 47

Лекция 10 �Кеширование, API, почта

intervolga.ru/school/

Ерофеев Анатолий Андреевич

ИНТЕРВОЛГА

Руководитель отдела разработки

2 of 47

Устройство ИНТЕРНЕТА,

HTTP, HTML, верстка

Веб-сервер�Лекции 1 и 2�ЛР 1

Работа с данными�PHP, MySQL, веб-формы, фильтрация данных�Лекции 3 и 4�ЛР 2

Работа с формами, куками, сессиями.

Авторизация, регистрация, проверка доступа�Лекции 5 и 6�ЛР 3

Обработка текста на PHP.

Организация длительных операций и точек доступа для AJAX�Лекции 7 и 8�ЛР 4

Работа с файлами и сетью. Кеширование и внешние API.�Лекции 9 и 10�ЛР 5

3 of 47

  • От браузера к диску: на каждом этапе выполняется код, который запрашивает данные с уровня ниже.�
  • Все это занимает время.�
  • Страница сайта может открываться несколько секунд, если есть:
    • «долгие» SQL-запросы
    • много вычислений
    • большая нагрузка на систему�
  • Пользователь нервничает, если сайт работает медленно.

ОС

СУБД

Программа

(сайт)

Браузер

4 of 47

  • От браузера к диску: на каждом этапе выполняется код, который запрашивает данные с уровня ниже.�
  • Все это занимает время.�
  • Страница сайта может открываться несколько секунд, если есть:
    • «долгие» SQL-запросы
    • много вычислений
    • большая нагрузка на систему�
  • Пользователь нервничает, если сайт работает медленно.

Есть разные способы сделать сайт быстрее:

  • вертикальное масштабирование: использовать более быстрый сервер
    • дешево, по сравнению с ЗП программиста
  • кеширование
    • относительно дешево
  • оптимизация
    • дорого
  • горизонтальное масштабирование: запустить проект на нескольких серверах и распределить нагрузку
    • дорого

ОС

СУБД

Программа

(сайт)

Браузер

5 of 47

Что такое кеширование

Ключевая идея: возвращать ранее рассчитанный результат для указанных входных данных.

Ленивый кеш — самый частый способ реализации. Логика обработки запроса:

  • если нет кеша
    • выполнить «настоящий» код (долго)
    • записать результат в кеш
  • если есть кеш
    • вернуть результат из кеша (быстро)

Кеш похож на словарь:

  • ключ — входные данные, кешируемой функции
  • значение — соответствующие выходные данные + метаданные

Таких словарей (кешей) в программе может быть несколько, а может быть один, принципиальной разницы нет.

6 of 47

У контроллера жесткого диска часто есть собственный небольшой кеш.

Он позволяет быстрее считывать данные, к которым чаще всего обращаются.

ОС

СУБД

Программа

(сайт)

Браузер

7 of 47

У контроллера жесткого диска часто есть собственный небольшой кеш.

Он позволяет быстрее считывать данные, к которым чаще всего обращаются.

При вызове fopen/fread/fseek и пр. операционная система не всегда обращается напрямую к диску.

ОС хранит части диска в оперативной памяти.

ОС

СУБД

Программа

(сайт)

Браузер

8 of 47

СУБД не всегда обращается к ОС для чтения своих файлов, потому что системные вызовы выполняются не быстро.

Части этих файлов хранятся в оперативной памяти.

В MySQL это называется buffer pool.

ОС

СУБД

Программа

(сайт)

Браузер

9 of 47

СУБД не всегда обращается к ОС для чтения своих файлов, потому что системные вызовы выполняются не быстро.

Части этих файлов хранятся в оперативной памяти.

В MySQL это называется buffer pool.

В СУБД может быть кеш запросов:

ключ — текст SQL-запроса�значение — результирующий набор (строки)

В MySQL 8+ эта функция удалена. Она делает производительность СУБД непредсказуемой.

ОС

СУБД

Программа

(сайт)

Браузер

10 of 47

Программа может кешировать некоторые SQL-запросы.

Программа может кешировать запросы к внешним сервисам.

ОС

СУБД

Программа

(сайт)

Браузер

11 of 47

Программа может кешировать некоторые SQL-запросы.

Программа может кешировать запросы к внешним сервисам.

Сайт может кешировать целые HTML-страницы или части страниц:

  • если нет кеша
    • сделать запрос к БД
    • сгенерировать HTML
    • сохранить HTML в кеш
  • если есть кеш
    • отдать готовый HTML

ОС

СУБД

Программа

(сайт)

Браузер

12 of 47

Браузер может кешировать HTTP-ответы сервера.

Чаще всего это используют для редко изменяющихся документов (CSS, JS, картинки…).

ОС

СУБД

Программа

(сайт)

Браузер

13 of 47

Инвалидация кеша

  • Если исходные данные изменились, данные в кеше нужно обновить, иначе пользователь будет получать устаревшие выходные данные.�
  • Обычно кеш просто очищают при изменении данных — при следующих запросах свежие данные попадут в кеш.�
  • Есть несколько стратегий.

14 of 47

Инвалидация кеша: по времени

  • В метаданные кеша записывается время его создания.
  • Программист определяет срок жизни кеша.
  • При получении данных из кеша нужно проверить,�закончился срок его жизни или нет.
  • Если время вышло, то действовать так, словно кеша нет.

  • Легко реализовать.
  • Пользователь не сразу будет видеть свежие данные.
  • Такой кеш даже со сроком жизни 1 мин. может значительно повысить производительность.

15 of 47

Инвалидация кеша: очистка при изменении

  • Требуется доработать функции, которые изменяют данные в БД.
  • При изменении данных в БД очищать кеш.
  • Оптимизация: удалять только ту часть кеша, которая была построена из изменившихся данных (т. н. тегированный кеш).

  • Без оптимизации — легко реализовать, но такой кеш эффективен только при ничтожно малом кол-ве запросов на изменение данных.
  • С оптимизацией — может быть сложно.
  • Пользователь всегда видит свежие данные.

16 of 47

Инвалидация кеша: Least Recently Used (LRU)

  • Количество записей в словаре ограничено.
  • Записи в словаре упорядочены.
  • Если в кеше нашлась нужная запись, она просто используется, а перемещается наверх.
  • Новая запись добавления наверх, при этом самая последняя запись вытесняется (удаляется), если место в словаре закончилось.

  • Специализированный кеш: хранит только те данные, к которым чаще всего обращаются.
  • Используется только совместно с очисткой по времени или очисткой при изменении данных.

17 of 47

Эффективность кеширования

Общую эффективность кеша считают соотношением:

Кол-во попаданий (cache hits)

Кол-во запросов

Для отдельных видов кеширования есть специальные метрики.

Очистка кеша при изменении данных приводит к уменьшению кол-ва попаданий и увеличению кол-ва промахов (cache misses).

Эффективность связана с соотношением числа запросов на чтение и на запись.

Кеширование может снизить скорость выполнения программы, если в БД чаще пишут, чем читают.

18 of 47

HTTP-кеширование

19 of 47

Особенности нагрузки на WEB-сайт

Интернет-магазин «хищник.рф»

≈ 100 тыс визитов/мес, ≈ 7 страниц/визит

Сайты выполняют большое число однотипных задач от большого числа пользователей:

  • список товаров
  • детальная страница товара
  • корзина
  • заказ
  • информационные разделы (новости, адреса магазинов и т. д.)

Учетная система на базе «1С»

≈ 100 пользователей всего

  • ведение справочников
  • заказ
  • оплаты, отгрузки
  • построение сложных отчетов

Требуются примерно одинаковые серверы для обоих проектов.

20 of 47

Состав страницы сайта

На разных сайтах объем страницы сильно отличается.

Пример:

  • 40 КБ — HTML
  • 140 КБ — CSS
  • 1 МБ — JavaScript
  • 3 МБ — изображения
  • 170 КБ — шрифты

21 of 47

Состав страницы сайта

На разных сайтах объем страницы сильно отличается.

Пример:

  • 40 КБ — HTML
  • 140 КБ — CSS
  • 1 МБ — JavaScript
  • 3 МБ — изображения
  • 170 КБ — шрифты

Итого: сервер отдает 4.5 МБ в сжатом виде (gzip). Чтобы загрузить одну страницу, нужно около 100 HTTP-запросов.

Главная страница volsu.ru:�7.8 МБ, 150 запросов.

Браузер выполняет несколько запросов одновременно: обычно 6-8.

При повторном открытии той же страницы браузер загружает ≈ 50-100 КБ. Работает HTTP-кеширование.

22 of 47

Управление HTTP-кешированием

Браузер кеширует HTTP-ответы так, как ему скажет сервер.

Настройка кеширования выполняется с помощью заголовков в HTTP-ответе.

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

Для статического контента (CSS, JS, изображения) настройка заголовков выполняется на уровне веб-сервера.

Заголовки:

Cache-Control

Date�Last-Modified�If-Modified-Since

ETag�If-None-Match

23 of 47

Cache-Control

Первый раз браузер делает запрос как обычно.

В заголовке Cache-Control указано:

  • max-age=604800
    • время, в течение которого браузер может хранить ответ в кеше
    • 604800 сек = 168 дней
  • immutable
    • при необходимости снова скачать style.css браузер вообще не будет делать HTTP-запрос, а возьмет файл из кеша

GET /style.css HTTP/1.1

Host: example.com

HTTP/1.1 200 OK

Date: Tue, 09 Nov 2021 13:08:56 GMT

Cache-Control: max-age=604800, immutable

Content-Length: ...

...

24 of 47

Last-Modified, If-Modified-Since

Первый раз браузер делает запрос как обычно.

Cache-Control: no-cache означает, что браузер будет кешировать запрос, но перед использованием кеша должен спрашивать разрешение у сервера.

Браузер делает запрос с заголовком If-Modified-Since, который равен Date кешированного ответа.

Если сервер пришлет ответ 304 (без тела), то браузер может использовать ответ из своего кеша.

GET /style.css HTTP/1.1

Host: example.com

HTTP/1.1 200 OK

Date: Tue, 09 Nov 2021 13:08:56 GMT

Cache-Control: no-cache

Last-Modified: Mon, 08 Nov 2021 09:30:00 GMT

Content-Length: ...

...

GET /style.css HTTP/1.1

Host: example.com

If-Modified-Since: Tue, 09 Nov 2021 13:08:56 GMT

HTTP/1.1 304 Not Modified

Date: Wed, 10 Nov 2021 17:25:00 GMT

Last-Modified: Mon, 08 Nov 2021 09:30:00 GMT

25 of 47

ETag, If-None-Match

Первый раз браузер делает запрос как обычно.

Второй запрос браузер делает с заголовком If-None-Match, который равен ETag кешированного ответа.

Если сервер пришлет ответ 304 (без тела), то браузер может использовать ответ из своего кеша.

ETag — это обычно хеш запрашиваемого ресурса.

Если в запросе указан If-None-Match, то сервер игнорирует If-Modified-Since.

GET /style.css HTTP/1.1

Host: example.com

HTTP/1.1 200 OK

Date: Tue, 09 Nov 2021 13:08:56 GMT

Cache-Control: no-cache

ETag: "33a64df551425f"

Content-Length: ...

...

GET /style.css HTTP/1.1

Host: example.com

If-None-Match: "33a64df551425f"

HTTP/1.1 304 Not Modified

Date: Wed, 10 Nov 2021 17:25:00 GMT

ETag: "33a64df551425f"

26 of 47

Серверное кеширование

27 of 47

Что и когда кешировать

Самые распространенные случаи:

  • Долгие SQL-запросы (до 1-2 секунд)
    • один раз страница будет открываться долго, потом быстро
    • кешировать нужно сам запрос, либо HTML�
  • Обращения к внешним сервисам по HTTP
    • HTTP-запрос с сервера может выполняться долго + время выполнения страницы вашего сайта
    • кешировать HTTP-ответ�

28 of 47

Пример кеширования на сервере

Есть функция, которая возвращает из БД график работы сотрудника на указанный месяц в году.

findWorkSchedule($userId, $monthYear)

Функция делает сложный SQL-запрос.

Способ реализации:

  1. Сгенерировать ключ кеша, например�workSchedule_<userId>_<monthYear>
  2. Найти в кеше запись по ключу
    1. кеш должен вернуть только валидную запись (не истекшую по времени и т. п.)
  3. Если запись нашлась
    • Вернуть значение из кеша�
  4. Сделать запрос в БД
  5. Записать результат в кеш по ключу
  6. Вернуть результат

29 of 47

Пример кеширования на сервере

Есть функция, которая возвращает из БД график работы сотрудника на указанный месяц в году.

findWorkSchedule($userId, $monthYear)

Функция делает сложный SQL-запрос.

Способ реализации:

  • Сгенерировать ключ кеша, например�workSchedule_<userId>_<monthYear>
  • Найти в кеше запись по ключу
    • кеш должен вернуть только валидную запись (не истекшую по времени и т. п.)
  • Если запись нашлась
    • Вернуть значение из кеша�
  • Сделать запрос в БД
  • Записать результат в кеш по ключу
  • Вернуть результат

Если параметров много или они длинные, можно расчитать хеш, пример ключа:

workSchedule_<md5 от всех аргументов>

30 of 47

Способы хранения кеша в PHP

На локальном диске

Диск расположен на том же сервере, что и программа (сайт).

Обращения к диску будут самыми быстрыми по сравнению с другими популярными решениями.

Специальное ПО

На том же сервере, что и сайт, либо на отдельном сервере можно запустить:

  • memcached (хранит все в ОЗУ)
  • Redis (все в ОЗУ, но копирует на диск)
  • и пр.

Это сервисы ОС (запускаются при старте сервера и работают постоянно).

Являются хранилищами типа ключ–значение.

PHP взаимодействует с ними по сетевому протоколу.

31 of 47

Используйте готовые решения для кеширования

  • Symfony — PHP-фреймворк для корпоративных приложений
  • Он модульный, можно даже использовать его части по-отдельности.

  • Через Composer можно подключить модуль кеширования

32 of 47

Использование внешних API

33 of 47

Примеры интеграции с внешними сервисами

С участием пользователя:

  • Вход на сайт с помощью OIDC: «войти с помощью Google/Yandex/…»

Без участия пользователя:

  • Обновление курсов валют
  • Перевод текста с одного языка на другой
  • Импортировать отчеты по рекламным компаниям
  • Импортировать пользователей из Active Directory

34 of 47

REST API (с точки зрения пользователя)

REST API — совокупность принципов построения программного интерфейса для разработчиков ПО поверх протокола HTTP.

Чаще всего похож на удаленный вызов процедур: HTTP-запрос запрос вызывает функцию во внешнем сервисе, ее возвращаемое значение приходит в HTTP-ответе.

Тело запроса и ответа, чаще всего — JSON.

Метод HTTP указывает что сделать с ресурсом: считать, добавить, обновить…

GET /products/15 HTTP/1.1

Host: example.com

HTTP/1.1 200 OK

Content-Type: application/json

Content-Length: ...

{

"id": 15,

"name: "Ручка шариковая синяя",

"price": {

"amount": 25.0,

"currency": "RUB"

},

"inStock": true

}

35 of 47

Аутентификация в REST API

Оформление заказа, просмотр истории заказов, смена пароля и пр. — эти операции могут выполнить только авторизованные пользователи.

При вызове REST API часто нужно передавать ключ доступа (access token).

Способы получения ключа доступа:

  • API Key — внешний сервис выдает секретную строку, которую нужно указывать в каждом запросе.
  • Basic — с каждым запросом отправлять base64("login:password").
  • OAuth 2, authorization code flow — пользователь сам делает вход в Google/Yandex, наш сайт получает access token и может вызывать REST API от имени пользователя.
  • OAuth 2, client credentials — сервис выдает секретную строку, нужно вызвать API для аутентификации, чтобы получить access token, который нужен для вызова всех остальных функций.

GET /orders/15 HTTP/1.1

Authorization: Bearer d42a148795d9f25f89d4

...

GET /orders/15 HTTP/1.1

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

...

OAuth 2

Basic

36 of 47

Клиент API на языке программирования

Клиент — совокупность функций на конкретном языке программирования, которые позволяют вызывать REST API. В этих функциях написан код отправки HTTP-запроса и обработки ответа.

Для многих публичных API есть готовые клиенты. Используйте их.

Если не нашли — напишите свой.

37 of 47

Электронная почта

38 of 47

Структура электронного письма

  • Письмо состоит из заголовков и тела.
  • Может содержать только ASCII-символы; для юникода применяется специальное кодирование (MIME).
  • Каждая строка должна быть не больше 78 символов + CR LF
    • в наше время разрешены строки длиной 998 символов
  • Электронная почта появилась раньше HTTP. Структура письма сильно повлияла на формат HTTP.

Subject: How are you?

From: bob@example.com

To: alice@example.com

Cc: ...

Bcc: ...

Hi Alice,

What’s up?

39 of 47

Архитектура электронной почты

Яндекс.Почта

Mail.ru

Mail User Agent (MUA)

Прим.: Outlook

Mail User Agent (MUA)

Прим.: iOS Mail App

Mail Transfer Agent (MTA)

Прим.: Postfix, Dovecot

Mail Transfer Agent (MTA)

Прим.: Postfix, Dovecot

Mail Delivery Agent (MDA)

Прим.: Postfix, Dovecot

Mail Delivery Agent (MDA)

Прим.: Postfix, Dovecot

40 of 47

Архитектура электронной почты

Яндекс.Почта

Mail.ru

Mail User Agent (MUA)

Прим.: Outlook

Mail User Agent (MUA)

Прим.: iOS Mail App

Mail Transfer Agent (MTA)

Прим.: Postfix, Dovecot

Mail Transfer Agent (MUA)

Прим.: Postfix, Dovecot

Mail Delivery Agent (MDA)

Прим.: Postfix, Dovecot

Mail Delivery Agent (MDA)

Прим.: Postfix, Dovecot

SMTP

SMTP

IMAP

41 of 47

Архитектура электронной почты

Яндекс.Почта

Mail.ru

Mail User Agent (MUA)

Прим.: Outlook

Mail User Agent (MUA)

Прим.: iOS Mail App

Mail Transfer Agent (MTA)

Прим.: Postfix, Dovecot

Mail Transfer Agent (MUA)

Прим.: Postfix, Dovecot

Mail Delivery Agent (MDA)

Прим.: Postfix, Dovecot

Mail Delivery Agent (MDA)

Прим.: Postfix, Dovecot

SMTP

SMTP

IMAP

SMTP

IMAP

42 of 47

Отправка почты из командной строки

  • Для отправки почты нужен SMTP-клиент.�
  • Популярные:
    • sendmail — оригинальная версия, реализации Postfix, Dovecot и пр.
    • msmtp�
  • Клиент соединяется с SMTP-сервером и передает ему письмо.

user@host:~$ sendmail bob@example.com

How are you?

^D

user@host:~$ msmtp bob@example.com

How are you?

^D

43 of 47

Отправка почты из PHP

  • В конфигурационном файле php.ini указано, какую команду вызывать для отправки письма.�
  • В PHP есть функция mail, которая принимает:
    • адрес «кому»,
    • тему письма,
    • текст письма,
    • доп. заголовки (опционально)�
  • Эта функция создает письмо и вызывает команду для отправки.

sendmail_path = /usr/sbin/sendmail -t -i

<?php

mail('bob@example.com', 'Hi!', 'What’s up?');

php.ini

44 of 47

Отправка почты из PHP: PHPMailer

PHPMailer — библиотека для более удобной отправки почты.

Не использует sendmail, сама является SMTP-клиентом.

Можно установить через Composer.

45 of 47

Спам и почтовые атаки

  • В электронном письмо можно написать любые значения заголовков, в том числе попытаться отправить письмо от имени другого человека.�
  • Почтовые сервисы применяют множество способов защиты от злоумышленников.

Subject: Больше не надо учиться

From: teacher@example.com

To: st1@example.com

Cc: st2@example.com, st3@example.com

Ставлю всем 100 баллов автоматом,

больше не ходите на занятия!

Студент отправляет письмо:

46 of 47

Основные механизмы защиты почты

При отправке:

  • Для отправки письма обязательна аутентификация.�
  • Аутентифицированный пользователь может указать в From только свой адрес.

При получении:

  • SPF — проверка права сервера отправлять почту от имени домена @domain.com.�
  • DKIM — цифровая подпись писем.�
  • Обратный DNS — проверка, что IP закреплен за доменом @domain.com, от имени которого отправляют почту.

47 of 47

Пример SPF и DKIM

A�IPv4-адрес соответствующий домену

AAAA�IPv6-адрес

MX�Адрес почтового сервера входящей почты

TXT�Запись «общего назначения»