Поделиться через


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

Пакетная обработка JSON позволяет клиентам объединять несколько запросов в один объект JSON и один вызов HTTP, уменьшая циклы сетевых циклов и повышая эффективность. Microsoft Graph поддерживает пакетную обработку до 20 запросов в объект JSON.

В этой статье мы рассмотрим основы пакетной обработки JSON, как она работает и как ее можно использовать для оптимизации приложений.

Примечание.

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

Пример сценария

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

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

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

Создание пакетного запроса

Чтобы создать пакетный запрос, выполните приведенные далее действия.

  1. Укажите метод HTTP запроса как POST.

  2. Укажите конечную точку URL-адреса, направленную v1.0 на версию Или beta Microsoft Graph, и добавьте $batch сегмент к URL-адресу. То есть . https://graph.microsoft.com/v1.0/$batch

  3. Определите текст пакетного запроса следующим образом:

    1. Текст пакетного запроса JSON состоит из одного объекта JSON с одним обязательным свойством: requests. Это свойство представляет собой коллекцию отдельных запросов.
    2. Для каждого отдельного запроса можно передать следующие свойства.
    Свойство Описание
    id Обязательно. Строка. Значение корреляции для связывания отдельных ответов с запросами. Это значение позволяет серверу обрабатывать запросы в пакете в наиболее эффективном порядке. Без учета регистра. Должен быть уникальным в пакете, в противном случае пакетный запрос завершается ошибкой 400 с кодом ошибки.
    метод Обязательный аргумент. Метод HTTP, поддерживаемый для запроса, указанного в URL-адресе.
    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

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

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

{
  "requests": [
    {
      "id": "1",
      "method": "GET",
      "url": "/me/memberOf"
    },
    {
      "id": "2",
      "method": "GET",
      "url": "/me/planner/tasks"
    },
    {
      "id": "3",
      "method": "DELETE",
      "url": "/groups/0e226165-c685-41ce-8bfc-df8360ab325d"
    },
    {
      "id": "4",
      "url": "/users/161ab652-cdbc-490d-82a4-0ada1f0db247/getPasswordSingleSignOnCredentials",
      "method": "POST",
      "body": {},
      "headers": {"Content-Type": "application/json"}
    },
    {
      "id": "5",
      "url": "users?$select=id,displayName,userPrincipalName&$filter=city eq null&$count=true",
      "method": "GET",
      "headers": {
        "ConsistencyLevel": "eventual"
      }
    }
  ]
}

Обработка пакетного ответа JSON

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

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

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

Пример пакетного ответа JSON

В предыдущем примере предположим, что этот ответ:

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

{
    "responses": [
        {
            "id": "1",
            "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/beta/$metadata#directoryObjects",
                "@odata.nextLink": "https://graph.microsoft.com/beta/me/memberOf?$top=1&$skiptoken=RFNwdAoAAQAAAAAAAAAAFAAAAI45VMy0CO9Ei1L3Lr1q95UBAAAAAAAAAAAAAAAAAAAXMS4yLjg0MC4xMTM1NTYuMS40LjIzMzEGAAAAAAABURXWGePFEEGbudEn3SOTuQEDAQAAAQAAAAA",
                "value": [
                    {
                        "@odata.type": "#microsoft.graph.directoryRole",
                        "id": "21004afc-7bb2-4fe6-a1e1-074ebd3e52c1",
                        "deletedDateTime": null,
                        "description": "Can manage all aspects of users and groups, including resetting passwords for limited admins.",
                        "displayName": "User Administrator",
                        "roleTemplateId": "fe930be7-5e62-47db-91af-98c3a49a38b1"
                    }
                ]
            }
        },
        {
            "id": "2",
            "status": 403,
            "headers": {
                "Cache-Control": "no-cache",
                "X-ProxyCluster": "wus-001.tasks.osi.office.net",
                "X-OfficeCluster": "wus-001.tasks.osi.office.net",
                "X-Tasks-CorrelationId": "18a8e521-78a4-4129-9b6b-d678116464e7",
                "Content-Type": "application/json"
            },
            "body": {
                "error": {
                    "code": "",
                    "message": "You do not have the required permissions to access this item.",
                    "innerError": {
                        "date": "2025-02-13T10:17:05",
                        "request-id": "93b6f17e-c05d-4f45-ad2a-6665c708d8a0",
                        "client-request-id": "e70c5c1b-8b47-68c0-3171-3d22f5e0bd54"
                    }
                }
            }
        },
        {
            "id": "3",
            "status": 403,
            "headers": {
                "Cache-Control": "no-cache",
                "x-ms-resource-unit": "1",
                "Content-Type": "application/json"
            },
            "body": {
                "error": {
                    "code": "Authorization_RequestDenied",
                    "message": "Insufficient privileges to complete the operation.",
                    "innerError": {
                        "date": "2025-02-13T10:17:06",
                        "request-id": "93b6f17e-c05d-4f45-ad2a-6665c708d8a0",
                        "client-request-id": "e70c5c1b-8b47-68c0-3171-3d22f5e0bd54"
                    }
                }
            }
        },
        {
            "id": "4",
            "status": 405,
            "headers": {
                "Cache-Control": "no-cache",
                "x-ms-resource-unit": "1",
                "Content-Type": "application/json"
            },
            "body": {
                "error": {
                    "code": "Request_BadRequest",
                    "message": "Specified HTTP method is not allowed for the request target.",
                    "innerError": {
                        "date": "2025-02-13T10:21:18",
                        "request-id": "3a3b1bf7-3596-4493-8264-de81e028071f",
                        "client-request-id": "e5f9a304-2796-b7e8-ccce-dd989953ebc4"
                    }
                }
            }
        },
        {
            "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/beta/$metadata#users(id,displayName,userPrincipalName)",
                "@odata.count": 36,
                "value": [
                    {
                        "id": "10a1d484-cd1a-4162-a5a4-832370bac356",
                        "displayName": "Lynne Robbins",
                        "userPrincipalName": "LynneR@contoso.com"
                    }
                ]
            }
        }
    ]
}

Объяснение отдельных ответов в примере пакетного ответа

  • Запросы 1 и 5 выполнены успешно, как показано в коде 200 состояния.
  • Запросы 2 и 3 завершились сбоем 403 с кодом состояния, так как у вызывающего не было необходимых разрешений.
  • Сбой 405 запроса 4 с кодом состояния, так как конечная точка, указанная в свойстве URL-адреса запроса, в настоящее время находится только в beta , но URL-адрес запроса предназначен для v1.0 конечной точки Microsoft Graph. Хотя целевой URL-адрес не требует текста запроса, по-прежнему необходимо указать заголовки и пареметры текста , где пустой объект может быть только текстом .

Выстраивание последовательности запросов с помощью свойства 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.

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

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

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