Объединение нескольких HTTP-запросов с помощью пакетной обработки JSON

Пакетная обработка JSON позволяет оптимизировать приложение путем объединения нескольких запросов (до 20) в один объект JSON.

Рассмотрим клиента, который хочет создать представление следующих несвязанных данных:

  • Изображение, хранящееся в OneDrive
  • Список задач Планировщика
  • Календарь группы

Объединение трех этих запросов в один может значительно снизить задержку в сети, ускорив работу приложения.

Microsoft Graph реализует $batchсегмент пути URL-адреса OData для поддержки пакетной обработки JSON.

Пример. Первый пакетный запрос JSON

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

POST https://graph.microsoft.com/v1.0/$batch
Accept: application/json
Content-Type: application/json

{
  "requests": [
    {
      "id": "1",
      "method": "GET",
      "url": "/me/drive/root:/{file}:/content"
    },
    {
      "id": "2",
      "method": "GET",
      "url": "/me/planner/tasks"
    },
    {
      "id": "3",
      "method": "GET",
      "url": "/groups/{id}/events"
    },
    {
      "id": "4",
      "url": "/me",
      "method": "PATCH",
      "body": {
        "city" : "Redmond"
      },
      "headers": {
        "Content-Type": "application/json"
      }
    },
    {
      "id": "5",
      "url": "users?$select=id,displayName,userPrincipalName&$filter=city eq null&$count=true",
      "method": "GET",
      "headers": {
        "ConsistencyLevel": "eventual"
      }
    }
  ]
}

Объяснение формата пакетного запроса

Пакетные запросы всегда отправляются с помощью метода POST в конечную точку /$batch.

Текст пакетного запроса JSON состоит из одного объекта JSON с одним обязательным свойством: requests. Свойство requests представляет собой коллекцию отдельных запросов. Для каждого отдельного запроса можно передать следующие свойства.

Свойство Описание
id Обязательно. Строка. Значение корреляции для связывания отдельных ответов с запросами. Это значение позволяет серверу обрабатывать запросы в пакете в наиболее эффективном порядке. Без учета регистра. Должен быть уникальным в пакете.
метод Обязательный аргумент. Метод HTTP.
url Обязательный аргумент. Относительный URL-адрес ресурса для отдельного запроса. Таким образом, если абсолютный URL-адрес выглядит так: https://graph.microsoft.com/v1.0/users, то этот URL-адрес выглядит так: /users.
заголовки Не является обязательным, но требуется, когда указан элементbody. Объект JSON с парой ключей и значений для заголовков. Например, если требуется заголовок ConsistencyLevel , это свойство представляется как "headers": {"ConsistencyLevel": "eventual"}. Если предоставлен элемент body, должен быть включен заголовок Content-Type.
body Необязательно. Может быть объектом JSON или значением в кодировке BASE64 URL, например, если текст является изображением. Когда элемент body включен в запрос, объект headers должен содержать значение для свойства Content-Type.

Пример. Первый пакетный ответ JSON

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

HTTP/1.1 200 OK
Content-Type: application/json

{
  "responses": [
    {
      "id": "1",
      "status": 302,
      "headers": {
        "location": "https://b0mpua-by3301.files.1drv.com/y23vmagahszhxzlcvhasdhasghasodfi"
      }
    },
    {
      "id": "3",
      "status": 401,
      "body": {
        "error": {
          "code": "Forbidden",
          "message": "..."
        }
      }
    },
    {
      "id": "5",
      "status": 200,
      "headers": {
        "Cache-Control": "no-cache",
        "x-ms-resource-unit": "1",
        "OData-Version": "4.0",
        "Content-Type": "application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false;charset=utf-8"
      },
      "body": {
        "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,displayName,userPrincipalName)",
        "@odata.count": 12,
        "value": [
          {
            "id": "071cc716-8147-4397-a5ba-b2105951cc0b",
            "displayName": "Adele Vance",
            "userPrincipalName": "AdeleV@Contoso.com"
          }
        ]
      }
    },
    {
      "id": "2",
      "status": 200,
      "body": {
        "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#Collection(microsoft.graph.plannerTask)",
        "value": []
      }
    },
    {
      "id": "4",
      "status": 204,
      "body": null
    }
  ]
}

Объяснение формата пакетного ответа

Формат ответа для пакетных запросов JSON отличается от формата запроса следующим образом:

  • Свойство в основном объекте JSON называется responses, а не requests.
  • Порядок отображения ответов и запросов может отличаться.
  • Вместо метода и URL-адреса отдельные ответы имеют свойство status . Значением состояния является код состояния HTTP.
  • Свойство заголовков в каждом отдельном ответе представляет заголовки, возвращаемые сервером, например заголовки Cache-Control и Content-Type.

Пакетный ответ обычно содержит код состояния 200 или 400. Если пакетный запрос имеет неправильный формат, код состояния — 400. Если пакетный запрос пригоден для анализа, код состояния — 200. Код 200 состояния в заголовках ответов пакета не указывает, что отдельные запросы в пакете успешно выполнены. Вот почему каждый отдельный ответ в свойстве responses имеет код состояния.

Выстраивание последовательности запросов с помощью свойства dependsOn

Запросы в пакете, выполняемые в указанном порядке, можно указать с помощью свойства dependsOn . Это свойство представляет собой массив строк, который ссылается на идентификатор другого отдельного запроса. Например, в следующем запросе клиент указывает, что запросы должны выполняться в запросе порядка 1, затем запросе 2, затем запросе 4, а затем запросе 3.

{
  "requests": [
    {
      "id": "1",
      "method": "GET",
      "url": "..."
    },
    {
      "id": "2",
      "dependsOn": [ "1" ],
      "method": "GET",
      "url": "..."
    },
    {
      "id": "4",
      "dependsOn": [ "2" ],
      "method": "GET",
      "url": "..."
    },
    {
      "id": "3",
      "dependsOn": [ "4" ],
      "method": "GET",
      "url": "..."
    }
  ]
}

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

Совет

Пакет должен быть полностью последовательным или полностью параллельным.

Обход ограничения на длину URL-адреса с помощью пакетной обработки

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

Ограничения размера пакетов

  • В настоящее время в пакетный запрос JSON можно включить не более 20 отдельных запросов.
  • В зависимости от API- интерфейсов, входящих в пакетный запрос, базовые службы накладывают собственные ограничения регулирования , которые влияют на приложения, использующие Microsoft Graph для доступа к ним.
  • Запросы в пакете оцениваются отдельно в соответствии с применимыми ограничениями регулирования, и если какой-либо запрос превышает эти ограничения, он завершается ошибкой с состоянием 429.

Дополнительные сведения см в статье Регулирование и пакетная обработка.

Известные проблемы

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