Глава 7: Связь в реальном времени
Брайан Кукси - опубликовано 22 апреля 2014
В главе 6 мы узнали о разработке API, создав свои собственные и изучив несколько реальных примеров. На данный момент у нас есть много знаний, заработанных тяжелым трудом, и пора бы им начать окупаться. Давайте посмотрим, как заставить API работать на нас. В этой главе мы узнаем четыре способа связи в реальном времени через API.
Интеграции
Чтобы подготовить почву для нашего обсуждения, давайте напомним себе, почему API-интерфейсы полезны. Еще в главе 1 мы говорили, что API-интерфейсы упрощают обмен данными между двумя системами (веб-сайтами, рабочими столами, смартфонами).

Прямое совместное использование позволяет нам связывать системы вместе, чтобы сформировать интеграцию. Людям нравятся интеграции, потому что они облегчают жизнь. Благодаря интеграции вы можете что-то делать в одной системе, а другая будет обновляться автоматически.

Для наших целей мы разделим интеграции на две большие категории. Первую мы назовем «управляемые клиентом», когда человек взаимодействует с клиентом и хочет, чтобы данные сервера обновлялись. Другую мы назовем «управляемые сервером», когда человек что-то делает на сервере и требует, чтобы клиент знал об изменении.

Причина такого разделения интеграций сводится к одному простому факту: клиент — единственный, кто может инициировать общение. Помните, что клиент делает запросы, а сервер просто отвечает. Следствием этого ограничения является то, что изменения легко отправить с клиента на сервер, но трудно — в обратном направлении.
Интеграция, управляемая клиентом
Чтобы продемонстрировать, почему интеграция, управляемая клиентом, проста, давайте обратимся к нашей надежной пиццерии и ее API для заказа пиццы. Допустим, мы выпускаем приложение для смартфона, использующее API. В этом сценарии API пиццерии является сервером, а приложение для смартфона — клиентом. Клиент использует приложение, чтобы выбрать пиццу, а затем нажимает кнопку, чтобы разместить заказ. Как только кнопка нажата, приложение знает, что ему нужно сделать запрос к API пиццерии.

Рисунок 1. Пример взаимодействия, управляемого клиентом

В более общем смысле, когда человек взаимодействует с клиентом, клиент точно знает, когда данные изменяются, поэтому он может немедленно вызвать API, чтобы сообщить серверу. Нет никакой задержки (следовательно, происходит в реальном времени), и процесс эффективен, потому что для каждого действия, предпринимаемого человеком, делается только один запрос.
Интеграция, управляемая сервером
После размещения заказа на пиццу покупатель может захотеть узнать, когда пицца будет готова. Как мы используем API, чтобы предоставлять им обновления? Что ж, это немного сложнее. Покупатель не имеет отношения к приготовлению пиццы. Он ждет, пока пиццерия приготовит пиццу и обновит статус заказа. Другими словами, данные на сервере меняются, и клиент должен знать об этом. Тем не менее, если сервер не может делать запросы, мы, кажется, застряли!

Для решения этого типа проблемы мы используем вторую категорию интеграций. Есть ряд решений, которые разработчики программного обеспечения используют, чтобы обойти ограничение, что только клиенты могут отправлять запросы. Давайте посмотрим на каждое из таких решений.
Опрос / Polling
Когда клиент — единственный, кто может делать запросы, самое простое решение для поддержания его в актуальном состоянии с сервером — это просто запросить у сервера обновления. Это может быть выполнено путем многократного запроса одного и того же ресурса, метод, известный как опрос (polling).

В нашей пиццерии опрос статуса заказа может выглядеть следующим образом.

Рисунок 2. Пример опроса статуса заказа в нашей пиццерии

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

Конечно, у этого решения есть одна большая проблема. Это ужасно неэффективно. Большинство запросов, которые делает клиент, теряются, потому что ничего не изменилось. Хуже того, чтобы получать обновления раньше, необходимо сократить интервал опроса, в результате чего клиент будет делать больше запросов и становится еще более неэффективным. Это решение плохо масштабируется.
Долгий опрос (long polling)
Если бы запросы были бесплатными, то никто не заботился бы об эффективности, и каждый мог бы просто использовать опрос. К сожалению, обработка запросов обходится дорого. Чтобы API мог обрабатывать больше запросов, ему необходимо использовать больше серверов, что стоит больше денег. Если масштабировать эту громоздкую ситуацию до размеров Google или Facebook, вы заплатите немало за неэффективность. Следовательно, было приложено много усилий для оптимизации способа получения клиентом обновлений с сервера.

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

Давайте вернемся к приведенному выше примеру опроса, но на этот раз с сервером, который использует трюк с долгим опросом.

Рисунок 3. Пример долгого опроса

Это довольно умная техника. Он подчиняется правилу, что клиент отправляет первоначальный запрос, в то же время пользуясь тем фактом, что не существует правила, запрещающего серверу медленно отвечать. Пока и клиент, и сервер согласны с тем, что сервер будет удерживать запрос клиента, и клиент может поддерживать свое соединение с сервером открытым, он будет работать.

Каким бы изобретательным ни был долгий опрос, у него тоже есть некоторые недостатки. Мы пропустим технические детали, но есть проблемы, например, сколько запросов сервер может удерживать за раз или как восстановить, если клиент или сервер потеряют соединение. А пока мы скажем, что для некоторых сценариев ни одна из форм опроса не подходит.
Вебхуки
Некоторые продвинутые разработчики программного обеспечения думали: «если все наши проблемы в том, что клиент — единственный, кто делает запросы, почему бы не удалить это правило?» Так они и сделали. Результатом стали вебхуки (веб-перехватчики, webhooks) — техника, при которой клиент одновременно отправляет запросы и прослушивает их, позволяя серверу легко отправлять ему обновления.

Если это звучит как жульничество, потому что теперь у нас есть сервер, отправляющий запросы клиенту, не волнуйтесь, вам не сказали неправду. Вебхуки работают именно потому, что клиент тоже становится сервером! С технической точки зрения иногда очень легко расширить функциональность клиента, чтобы он также прослушивал запросы, обеспечивая двустороннюю связь.

Давайте посмотрим на суть вебхуков. В своей простейшей форме веб-перехватчики требуют, чтобы клиент предоставил URL-адрес обратного вызова, по которому он может получать события, а на сервере должно быть место для ввода этого URL-адреса обратного вызова. Затем, когда что-то изменяется на сервере, сервер может отправить запрос на URL-адрес обратного вызова клиента, чтобы сообщить клиенту об обновлении.

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

Рисунок 4. Использование вебхуков для получения обновлений (с Zapier в качестве клиента)

Это отличное решение. Изменения, происходящие на сервере, мгновенно отправляются клиенту, поэтому у вас есть настоящая связь в реальном времени. Кроме того, вебхуки эффективны, поскольку на одно обновление выполняется только один запрос.
Подписка на веб-перехватчики
Основываясь на идее вебхуков, было разработано множество решений, направленных на то, чтобы сделать процесс настройки динамичным и не требовать, чтобы человек вручную вводил URL-адрес обратного вызова на сервере. Вы можете услышать такие названия, как спецификация HTTP-подписок, Restful Webhooks, REST Hooks и PubSubHubbub . Все эти решения пытаются определить процесс подписки, в котором клиент может сообщить серверу, какие события ему интересны и по какому URL-адресу обратного вызова отправлять обновления.

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

Рисунок 5. Запросы, необходимые для веб-перехватчиков подписок

Веб-перехватчики по подписке многообещающи. Они эффективны, работают в режиме реального времени и просты в использовании. Подобно взрывному распространению REST, это движение растет, и API все чаще поддерживают ту или иную форму веб-перехватчиков.

Тем не менее, в обозримом будущем, скорее всего, найдется место для опросов и длительных опросов. Не все клиенты могут также выступать в качестве серверов. Смартфоны — отличный пример, когда технические ограничения исключают возможность использования веб-перехватчиков. По мере развития технологий будут появляться новые идеи о том, как упростить обмен данными в реальном времени между всеми видами устройств.
Краткое содержание главы 7
В этой главе мы сгруппировали интеграции по двум широким категориям: управляемые клиентом и управляемые сервером. Мы увидели, как API-интерфейсы могут использоваться для предоставления обновлений в реальном времени между двумя системами, а также некоторые сложности, с этим связанные.

Ключевые термины, которые мы узнали, были:

  • Опрос: многократный запрос ресурса с коротким интервалом.
  • Долгий опрос: опрос, но с отложенным ответом; повышает эффективность.
  • Вебхукт: когда клиент предоставляет серверу URL-адрес обратного вызова, чтобы сервер мог публиковать обновления в режиме реального времени.
  • Подписка на вебхуки: неофициальное название для решений, которые делают автоматическую настройку веб-перехватчиков.
Что дальше
В заключительной главе этого курса мы рассмотрим, что нужно, чтобы превратить проект API в работающее программное обеспечение.