Новые 5 способов ускорить запросы API Facebook

в 6:00, , рубрики: batch, Facebook, Facebook API, graph api, оптимизация, метки: , , , ,

Прошлой осенью я публиковал на Хабре пост Пять способов ускорить запросы API Facebook на практике, который оказался неплохим сборником рецептов. За это время Facebook API сильно изменился, став еще лучше. Теперь я редко встречаю задачи, с которыми я бы не смог справиться за один HTTP запрос к API. А все благодаря новым возможностям, о которых я и расскажу сейчас.

image

Вот какие способы были в прошлый раз:

  1. Запрашиваем только необходимые поля
    me?fields=id,name,birthday
  2. Запрашиваем данные нескольких объектов в одном запросе
    ?ids=4,501012028
  3. Используем фильтрацию и пагинацию
    me/friends?limit=10&offset=10
  4. Используем запросы FQL
    fql?q=SELECT uid, name, birthday_date FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me())
  5. Отправляем Batch Request с несколькими запросами
    batch=[{«method»:«GET», «relative_url»:«me»},{«method»:«GET», «relative_url»:«me/friends?limit=50»}]


Все запросы можно выполнить в Graph API Explorer, который теперь поддерживает FQL запросы.

1) Multi-query

Multi-query – это несколько запросов FQL, которые отправляются в одном Graph API запросе. Multi-query обрабатываются быстрее, чем такая же пачка FQL запросов, отправленных через Batch Request. При этом они не только могут передать ответ по нескольким объектам, но и решают одну из проблем простых FQL запросов.

Допустим вы хотите получить список пользователей, которые собираются посетить определенное мероприятие. Вы пишете FQL запрос:
SELECT name, url, pic FROM profile WHERE id IN (SELECT uid FROM event_member WHERE eid=12345678)

Но такой запрос дает вам всех пользователей, не давая информации о статусе (attending, unsure, declined, not_replied). Все хорошо, если вам нужно выводить информацию только тех, кто пойдет на мероприятие. Тогда вы просто добавляете в условие вложенного запроса AND rsvp_status = 'attending'. Но что вам делать, если на одной странице вам нужно отобразить всех пользователей, разбив их по статусам RSVP. Делать 4 FQL запроса c разными условиями и отправлять их с помощью batch?

Facebook предлагает вам составить два запроса и использовать данные одного во втором. Для нашего примера запросы будут следующими:
«query1»:«SELECT uid, rsvp_status FROM event_member WHERE eid=12345678»
«query2»:«SELECT name, url, pic FROM profile WHERE id IN (SELECT uid FROM #query1)»
Теперь за один запрос вы получите все необходимые данные, причем это будет быстрее, чем через batch.

Подробнее про Multi-query вы можете посмотреть в документации.

2) Batch Requests containing multiple methods and dependencies between operations

Теперь в одном batch запросе вы можете передавать разные HTTP методы: GET, POST, DELETE. Например, опубликовать новый статус и вернуть новостную ленту пользователя за один запрос. Но плюшки не в этом, а в “зависимостях”.

Изначально запросы были независимыми. Но сейчас вы можете использовать данные одного запроса в другом, при этом управлять зависимостями с помощью JSONPath выражений.

Самый простой пример: получить данные 5-и друзей. Это можно сделать с помощью такого запроса:
batch=[{«method»:«GET»,«name»:«get-friends»,«relative_url»:«me/friends?limit=5»,},{«method»:«GET»,«relative_url»:"?ids={result=get-friends:$.data.*.id}"}]

Стоп! Так это же мы можем сделать и с помощью Multi-query, скажете вы. Да, пример нужно подобрать другой, чтобы показать всю мощь. А как вам этот:
batch=[{ «method»:«GET»,«name»:«one-friend»,«relative_url»:«me/friends?limit=1»,},{ «method»:«POST», «relative_url»:«me/feed», «body»:«message={result=one-friend:$.data.0.name} is my friend»}]
Мы получаем одного из друзей пользователя и используем его данные для того, чтобы опубликовать новый пост. Не нужно двух отдельных запросов.

Вы можете использовать до 50-и запросов в batch, управлять поведением запросов с помощью параметров omit_response_on_success и depends_on, а также использовать разные access_token (пользователя, страницы, приложения) в разных запросах. Документация по Batch Requests.

3) ETags

В начале года Facebook поддержал HTTP ETags. Принцип их работы прост:

  1. Когда вы выполняете Graph API запрос, в ответе вам придет заголовок ETag со значением, которое является хэшем данных, возращаемых через API.
  2. Когда в следующий раз вы будете вызывать этот же запрос, передайте заголовок If-None-Match с данными, полученными из пункта 1.
  3. Если данные не изменились, вы получите в ответ 304 – Not Modified без данных.
  4. Если данные изменились – данные возвращаются как обычно (пункт 1).

Использовать это желательно с теми данными, которые не меняются часто. Например, не стоит использовать ETags в запросах ленты новостей или сообщений. Но для запросов списка друзей в мобильных приложениях на медленных подключениях производительность конечно повысится.

Подробнее про ETags а также пример кода вы можете посмотреть в этом посте в блоге разработчиков.

4) Field expansion

Выше я уже описал два способа, как можно получить в одном запросе данные из связанных объектов с помощью Multi-query и Batch с JSONPath. Но для Graph API запросов есть вариант проще.

Например, мы хотим вывести на станице имя пользователя, его день рождения и последние 10 фотографий. Все это мы можем сделать с помощью такого запроса:
me?fields=name,birthday,photos.limit(10).fields(id, picture)

Или мы хотим выводить комментарии к фотографии, но нам недостаточно стандартных полей, и мы хотим добавить еще день рождения комментаторов. Запрос следующий:
<photo_id>/comments?fields=from.fields(id, name, birthday)

Такие запросы вы можете составлять для всех identifiers, fields and connections. Не правда ли, намного легче и удобнее? Документация по field expansion.

5) Pagination

В прошлой статье я уже писал про фильтрацию и пагинацию с помощью filter и offset. Хотя этот способ весьма полезен, но у него все же есть один большой недостаток. В каждом запросе у вас выводятся ссылки previous и next несмотря на то, существуют ли за ними данные, или нет.

Facebook предлагает новое решение: cursor-based offset paging. Вам больше не будут показывать previous и next, если больше нет данных. Если есть предыдущая/следующая страница, будут отображены ссылки before/after в запросе. Вы сэкономите “один проход”, просматривая каждую коллекцию объектов.

К сожалению, Cursor-based Pagination пока есть не для всех объектов. Но это уже вопрос времени. Следите за документацией и используйте более эффективные решения.

Ну а если вы использовали все возможности для оптимизации, не забудьте посмотреть статью Оптимизируем запросы к Facebook Graph API с помощью Real-Time Updates.

В заключение хотел напомнить, что 1-го октября в Москве будет Facebook Developer HACK 2012. Если вы не сможете присутствовать лично, оставьте свои вопросы в комментариях. Лично у меня скопилось достаточно вопросов к инженерам Facebook.

Автор: antonsnowy

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js