Перейти к основному содержимому

Сеть и HTTP

Что происходит между тем, как запрос ушёл из приложения, и тем, как пришёл ответ: методы, коды состояния, заголовки, кэширование, соединения — и множество способов, которыми этот обмен ломается на настоящем телефоне в настоящей сети.

Почему это важно. Мобильные сети медленные, теряют пакеты и постоянно пропадают. Приложение, написанное так, будто сеть — это обычный вызов функции, прекрасно работает по Wi-Fi за рабочим столом и разваливается в лифте, в электричке или в тот день, когда backend не упал, а всего лишь деградировал.

Что нужно понимать

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

Ключевые темы

Запрос

  • Методы и что каждый из них должен означать — включая идемпотентность
  • Заголовки, которые важны на практике: тип содержимого, авторизация, управление кэшем, условные запросы
  • Строки запроса, параметры пути и тело запроса

Ответ

  • Классы кодов состояния и те, в которых чаще всего ошибаются: 401 против 403, 404 против 204, 409, 422, 429
  • Тела ошибок, на которые клиент может отреагировать, а не только показать их пользователю
  • Согласование содержимого и сжатие

Соединения и задержки

  • TLS, рукопожатия и почему переиспользование соединения значит больше, чем размер полезной нагрузки
  • HTTP/2 и HTTP/3 в одном абзаце: мультиплексирование и head-of-line blocking
  • Таймауты — на подключение, на чтение, общий — и осознанный выбор их значений

Отказы и восстановление

  • Повторные попытки, backoff и jitter
  • Почему повторять неидемпотентный запрос — это ошибка
  • Отмена запроса: не платить за ответ, который никто не прочитает
  • Отсутствие сети, нестабильная сеть и медленная сеть — три разные задачи

За пределами запроса и ответа

  • WebSockets и server-sent events
  • Опрос, long polling — и когда каждый из них честен

Уровни

УровеньКак это выглядит
JuniorДелает запросы, обрабатывает успех и одну общую ошибку, смотрит коды состояния в документации.
MiddleРазличает классы ошибок и реагирует на них по-разному. Ставит таймауты, безопасно повторяет запросы, обрабатывает отмену.
SeniorПроектирует всё поведение клиента при сбоях — политику повторов, кэширование, работу без сети — и умеет найти, где на самом деле возникает задержка.

Практика

Для начала

  • Обработайте каждый класс ошибок Возьмите экран, который показывает одну общую ошибку, и сделайте так, чтобы 401, 404, 422 и 500 вели себя по-разному и с пользой.

  • Добавьте таймауты Задайте каждому запросу осознанный таймаут и посмотрите, что делает интерфейс, когда он срабатывает.

  • Прочитайте трафик Посмотрите запросы собственного приложения в DevTools и объясните каждый из них.

Глубже

  • Повторяйте правильно Добавьте экспоненциальный backoff с jitter и убедитесь, что повторяются только идемпотентные запросы.

  • Кэшируйте по условию Используйте ETag или Last-Modified, чтобы неизменившиеся данные стоили одного обращения и ни байта данных.

  • Переживите плохую сеть Проверьте работу на медленных и рвущихся соединениях и почините то, что сломается.

Проверьте себя

  • Какие запросы вашего приложения безопасно повторять — и откуда вы это знаете?
  • Что делает приложение, когда сервер отвечает медленно, а не падает с ошибкой?
  • Как вы выбираете значение таймаута?
  • Что кэшируется в вашем приложении сегодня и кто это решил — вы или значение по умолчанию?
  • Как отличить медленный сервер от медленной сети?
  • Что происходит с запросом в полёте, когда пользователь уходит с экрана?

Материалы

  • MDN HTTP reference — справочник по методам, заголовкам, кодам состояния и кэшированию. Точный, полный и такой, на котором заканчиваются споры.
  • High Performance Browser Networking — книга Ильи Григорика, целиком доступная бесплатно. Главы про TCP, TLS и мобильные сети объясняют, на что уходит время запроса, лучше всего остального написанного на эту тему.
  • HTTP Caching — заслуживает отдельного пункта: среди сетевых тем кэширование даёт наибольшую отдачу и чаще всего оказывается пропущенным.
  • Timeouts, retries and backoff with jitter — из Amazon Builders' Library. Самое ясное объяснение того, почему наивные повторы только усугубляют аварию.
  • dart:io HttpClient и package:http — то, что даёт сам Dart, и слой, которым на деле пользуется большинство проектов.