Советы по производительности

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

Сжатие с помощью gzip

Простой и удобный способ уменьшить пропускную способность, необходимую для каждого запроса, — включить сжатие gzip. Хотя для распаковки результатов требуется дополнительное время процессора, компромисс с сетевыми затратами обычно делает это весьма выгодным.

Чтобы получить ответ в кодировке gzip, вы должны сделать две вещи: установить заголовок Accept-Encoding и изменить свой пользовательский агент, чтобы он содержал строку gzip . Вот пример правильно сформированных HTTP-заголовков для включения сжатия gzip:

Accept-Encoding: gzip
User-Agent: my program (gzip)

Работа с частичными ресурсами

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

Существует два типа частичных запросов:

  • Частичный ответ : запрос, в котором вы указываете, какие поля включить в ответ (используйте параметр запроса fields ).
  • Исправление : запрос на обновление, при котором вы отправляете только те поля, которые хотите изменить (используйте HTTP-команду PATCH ).

Более подробная информация о выполнении частичных запросов представлена ​​в следующих разделах.

Частичный ответ

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

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

Обратите внимание, что параметр fields влияет только на данные ответа; это не влияет на данные, которые вам нужно отправить, если таковые имеются. Чтобы уменьшить объем данных, отправляемых при изменении ресурсов, используйте запрос на исправление .

Пример

В следующем примере показано использование параметра fields с универсальным (вымышленным) «Демо» API.

Простой запрос: этот HTTP-запрос GET опускает параметр fields и возвращает полный ресурс.

https://www.googleapis.com/demo/v1

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

{
  "kind": "demo",
  ...
  "items": [
  {
    "title": "First title",
    "comment": "First comment.",
    "characteristics": {
      "length": "short",
      "accuracy": "high",
      "followers": ["Jo", "Will"],
    },
    "status": "active",
    ...
  },
  {
    "title": "Second title",
    "comment": "Second comment.",
    "characteristics": {
      "length": "long",
      "accuracy": "medium"
      "followers": [ ],
    },
    "status": "pending",
    ...
  },
  ...
  ]
}

Запрос на частичный ответ: следующий запрос для этого же ресурса использует параметр fields , чтобы значительно уменьшить объем возвращаемых данных.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

Частичный ответ: в ответ на приведенный выше запрос сервер отправляет обратно ответ, который содержит только информацию о типе, а также урезанный массив элементов, который включает только информацию о названии и длине HTML в каждом элементе.

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

Обратите внимание, что ответ представляет собой объект JSON, который включает только выбранные поля и включающие их родительские объекты.

Подробности о форматировании параметра fields рассматриваются далее, а затем более подробная информация о том, что именно возвращается в ответе.

Сводка синтаксиса параметров полей

Формат значения параметра запроса fields во многом основан на синтаксисе XPath. Поддерживаемый синтаксис кратко описан ниже, а дополнительные примеры приведены в следующем разделе.

  • Используйте список, разделенный запятыми, чтобы выбрать несколько полей.
  • Используйте a/b , чтобы выбрать поле b вложенное в поле a ; используйте a/b/c чтобы выбрать поле c вложенное в b .

    Исключение: для ответов API, использующих оболочки «данных», где ответ вложен в объект data , который выглядит как data: { ... } , не включайте « data » в спецификацию fields . Включение объекта данных со спецификацией полей, например data/a/b приводит к ошибке. Вместо этого просто используйте спецификацию fields , например a/b .

  • Используйте дополнительный селектор, чтобы запросить набор определенных подполей массивов или объектов, помещая выражения в круглые скобки " ( ) ".

    Например: fields=items(id,author/email) возвращает только идентификатор элемента и адрес электронной почты автора для каждого элемента массива элементов. Вы также можете указать одно подполе, где fields=items(id) эквивалентны fields=items/id .

  • При необходимости используйте подстановочные знаки при выборе полей.

    Например: fields=items/pagemap/* выбирает все объекты в карте страниц.

Дополнительные примеры использования параметра полей

В приведенных ниже примерах описано, как значение параметра fields влияет на ответ.

Примечание. Как и все значения параметров запроса, значение параметра fields должно быть закодировано в URL-адресе. Для лучшей читаемости в примерах в этом документе кодировка не указана.

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

Вот несколько примеров на уровне коллекции:
Примеры Эффект
items Возвращает все элементы массива items, включая все поля в каждом элементе, но не другие поля.
etag,items Возвращает поле etag и все элементы массива items.
items/title Возвращает только поле title для всех элементов массива элементов.

Всякий раз, когда возвращается вложенное поле, ответ включает в себя включающие его родительские объекты. Родительские поля не включают в себя другие дочерние поля, если они также не выбраны явно.
context/facets/label Возвращает только поле label для всех членов массива facets , который сам вложен в объект context .
items/pagemap/*/title Для каждого элемента массива items возвращает только поле title (если оно присутствует) всех объектов, которые являются дочерними элементами pagemap .

Вот несколько примеров на уровне ресурсов:
Примеры Эффект
title Возвращает поле title запрошенного ресурса.
author/uri Возвращает подполе uri объекта author в запрошенном ресурсе.
links/*/href
Возвращает поле href всех объектов, являющихся дочерними элементами links .
Запрашивайте только части определенных полей, используя подвыборки .
По умолчанию, если в вашем запросе указаны определенные поля, сервер возвращает объекты или элементы массива целиком. Вы можете указать ответ, который включает только определенные подполя. Вы делаете это, используя синтаксис подвыбора " ( ) ", как в примере ниже.
Пример Эффект
items(title,author/uri) Возвращает только значения title и uri автора для каждого элемента массива items.

Обработка частичных ответов

После того как сервер обрабатывает действительный запрос, включающий параметр запроса fields , он отправляет обратно код состояния HTTP 200 OK вместе с запрошенными данными. Если параметр запроса fields имеет ошибку или по какой-либо причине недействителен, сервер возвращает код состояния HTTP 400 Bad Request вместе с сообщением об ошибке, сообщающим пользователю, что было неправильно с выбором полей (например, "Invalid field selection a/b" ).

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

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

Частичный ответ выглядит так:

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

Примечание. Для API, которые поддерживают параметры запроса для разбивки данных на страницы (например, maxResults и nextPageToken ), используйте эти параметры, чтобы уменьшить результаты каждого запроса до управляемого размера. В противном случае выигрыш в производительности, возможный при частичном отклике, может быть не реализован.

Патч (частичное обновление)

Вы также можете избежать отправки ненужных данных при изменении ресурсов. Чтобы отправлять обновленные данные только для определенных полей, которые вы меняете, используйте команду HTTP PATCH . Семантика исправлений, описанная в этом документе, отличается (и проще), чем для старой реализации частичного обновления GData.

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

Пример

В этом примере показан простой запрос на исправление для обновления только заголовка общего (вымышленного) ресурса API «Демо». Ресурс также имеет комментарий, набор характеристик, статус и многие другие поля, но этот запрос отправляет только поле title , поскольку это единственное поле, которое модифицируется:

PATCH https://www.googleapis.com/demo/v1/324
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "title": "New title"
}

Ответ:

200 OK
{
  "title": "New title",
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "accuracy": "high",
    "followers": ["Jo", "Will"],
  },
  "status": "active",
  ...
}

Сервер возвращает код состояния 200 OK вместе с полным представлением обновленного ресурса. Поскольку в запрос на исправление было включено только поле title , это единственное значение, которое отличается от предыдущего.

Примечание. Если вы используете параметр fields частичного ответа в сочетании с патчем, вы можете еще больше повысить эффективность запросов на обновление. Запрос на исправление только уменьшает размер запроса. Частичный ответ уменьшает размер ответа. Поэтому, чтобы уменьшить объем данных, отправляемых в обоих направлениях, используйте запрос исправления с параметром fields .

Семантика запроса на исправление

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

  • Добавить: Чтобы добавить поле, которого еще нет, укажите новое поле и его значение.
  • Изменить: Чтобы изменить значение существующего поля, укажите поле и установите для него новое значение.
  • Удалить: Чтобы удалить поле, укажите поле и установите для него значение null . Например, "comment": null . Вы также можете удалить весь объект (если он изменяем), установив для него значение null . Если вы используете клиентскую библиотеку Java API , вместо этого используйте Data.NULL_STRING ; подробности см. в разделе JSON null .

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

Использование патча в цикле чтения-изменения-записи

Будет полезно начать с получения частичного ответа с данными, которые вы хотите изменить. Это особенно важно для ресурсов, использующих ETag, поскольку для успешного обновления ресурса необходимо указать текущее значение ETag в HTTP-заголовке If-Match . После получения данных вы можете изменить значения, которые хотите изменить, и отправить измененное частичное представление обратно с запросом на исправление. Вот пример, в котором предполагается, что демонстрационный ресурс использует ETags:

GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token

Это частичный ответ:

200 OK
{
  "etag": "ETagString"
  "title": "New title"
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "level": "5",
    "followers": ["Jo", "Will"],
  }
}

Следующий запрос на исправление основан на этом ответе. Как показано ниже, он также использует параметр fields для ограничения данных, возвращаемых в ответе на исправление:

PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json
If-Match: "ETagString"
{
  "etag": "ETagString"
  "title": "",                  /* Clear the value of the title by setting it to the empty string. */
  "comment": null,              /* Delete the comment by replacing its value with null. */
  "characteristics": {
    "length": "short",
    "level": "10",              /* Modify the level value. */
    "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */
    "accuracy": "high"          /* Add a new characteristic. */
  },
}

Сервер отвечает кодом состояния HTTP 200 OK и частичным представлением обновленного ресурса:

200 OK
{
  "etag": "newETagString"
  "title": "",                 /* Title is cleared; deleted comment field is missing. */
  "characteristics": {
    "length": "short",
    "level": "10",             /* Value is updated.*/
    "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */
    "accuracy": "high"         /* New characteristic is present. */
  }
}

Создание запроса на исправление напрямую

Для некоторых запросов на исправления вам необходимо основывать их на ранее полученных данных. Например, если вы хотите добавить элемент в массив и не хотите потерять ни один из существующих элементов массива, вы должны сначала получить существующие данные. Аналогично, если API использует ETag, вам необходимо отправить предыдущее значение ETag вместе с вашим запросом, чтобы успешно обновить ресурс.

Примечание. Вы можете использовать HTTP-заголовок "If-Match: *" чтобы принудительно пройти исправление, когда используются ETags. Если вы сделаете это, вам не нужно будет выполнять чтение перед записью.

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

PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "comment": "A new comment",
  "characteristics": {
    "volume": "loud",
    "accuracy": null
  }
}

При этом запросе, если поле комментария имеет существующее значение, новое значение перезаписывает его; в противном случае ему будет присвоено новое значение. Аналогично, если была характеристика объема, ее значение перезаписывается; если нет, то он создается. Поле точности, если оно установлено, удаляется.

Обработка ответа на патч

После обработки действительного запроса на исправление API возвращает код ответа HTTP 200 OK вместе с полным представлением измененного ресурса. Если API использует ETag, сервер обновляет значения ETag при успешной обработке запроса на исправление, как и в случае с PUT .

Запрос на исправление возвращает полное представление ресурса, если только вы не используете параметр fields , чтобы уменьшить объем возвращаемых данных.

Если запрос на исправление приводит к новому состоянию ресурса, которое является синтаксически или семантически недопустимым, сервер возвращает код состояния HTTP 400 Bad Request или 422 Unprocessable Entity , а состояние ресурса остается неизменным. Например, если вы попытаетесь удалить значение обязательного поля, сервер вернет ошибку.

Альтернативная запись, если HTTP-команда PATCH не поддерживается.

Если ваш брандмауэр не разрешает запросы HTTP PATCH , выполните запрос HTTP POST и установите для заголовка переопределения значение PATCH , как показано ниже:

POST https://www.googleapis.com/...
X-HTTP-Method-Override: PATCH
...

Разница между патчем и обновлением

На практике, когда вы отправляете данные для запроса на обновление, использующего команду HTTP PUT , вам нужно отправлять только те поля, которые являются обязательными или необязательными; если вы отправляете значения для полей, установленных сервером, они игнорируются. Хотя это может показаться еще одним способом частичного обновления, у этого подхода есть некоторые ограничения. При обновлениях, в которых используется команда HTTP PUT , запрос завершается неудачей, если вы не указываете обязательные параметры, и очищает ранее установленные данные, если вы не указываете дополнительные параметры.

По этой причине гораздо безопаснее использовать патч. Вы предоставляете данные только для тех полей, которые хотите изменить; поля, которые вы пропускаете, не очищаются. Единственное исключение из этого правила возникает с повторяющимися элементами или массивами: если вы опустите их все, они останутся такими, какие есть; если вы предоставите какой-либо из них, весь набор будет заменен предоставленным вами набором.

,

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

Сжатие с помощью gzip

Простой и удобный способ уменьшить пропускную способность, необходимую для каждого запроса, — включить сжатие gzip. Хотя для распаковки результатов требуется дополнительное время процессора, компромисс с сетевыми затратами обычно делает это весьма выгодным.

Чтобы получить ответ в кодировке gzip, вы должны сделать две вещи: установить заголовок Accept-Encoding и изменить свой пользовательский агент, чтобы он содержал строку gzip . Вот пример правильно сформированных HTTP-заголовков для включения сжатия gzip:

Accept-Encoding: gzip
User-Agent: my program (gzip)

Работа с частичными ресурсами

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

Существует два типа частичных запросов:

  • Частичный ответ : запрос, в котором вы указываете, какие поля включить в ответ (используйте параметр запроса fields ).
  • Исправление : запрос на обновление, при котором вы отправляете только те поля, которые хотите изменить (используйте HTTP-команду PATCH ).

Более подробная информация о выполнении частичных запросов представлена ​​в следующих разделах.

Частичный ответ

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

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

Обратите внимание, что параметр fields влияет только на данные ответа; это не влияет на данные, которые вам нужно отправить, если таковые имеются. Чтобы уменьшить объем данных, отправляемых при изменении ресурсов, используйте запрос на исправление .

Пример

В следующем примере показано использование параметра fields с универсальным (вымышленным) «Демо» API.

Простой запрос: этот HTTP-запрос GET опускает параметр fields и возвращает полный ресурс.

https://www.googleapis.com/demo/v1

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

{
  "kind": "demo",
  ...
  "items": [
  {
    "title": "First title",
    "comment": "First comment.",
    "characteristics": {
      "length": "short",
      "accuracy": "high",
      "followers": ["Jo", "Will"],
    },
    "status": "active",
    ...
  },
  {
    "title": "Second title",
    "comment": "Second comment.",
    "characteristics": {
      "length": "long",
      "accuracy": "medium"
      "followers": [ ],
    },
    "status": "pending",
    ...
  },
  ...
  ]
}

Запрос на частичный ответ: следующий запрос для этого же ресурса использует параметр fields , чтобы значительно уменьшить объем возвращаемых данных.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

Частичный ответ: в ответ на приведенный выше запрос сервер отправляет обратно ответ, который содержит только информацию о типе, а также урезанный массив элементов, который включает только информацию о названии и длине HTML в каждом элементе.

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

Обратите внимание, что ответ представляет собой объект JSON, который включает только выбранные поля и включающие их родительские объекты.

Подробности о форматировании параметра fields рассматриваются далее, а затем более подробная информация о том, что именно возвращается в ответе.

Сводка синтаксиса параметров полей

Формат значения параметра запроса fields во многом основан на синтаксисе XPath. Поддерживаемый синтаксис кратко описан ниже, а дополнительные примеры приведены в следующем разделе.

  • Используйте список, разделенный запятыми, чтобы выбрать несколько полей.
  • Используйте a/b , чтобы выбрать поле b вложенное в поле a ; используйте a/b/c чтобы выбрать поле c вложенное в b .

    Исключение: для ответов API, использующих оболочки «данных», где ответ вложен в объект data , который выглядит как data: { ... } , не включайте « data » в спецификацию fields . Включение объекта данных со спецификацией полей, например data/a/b приводит к ошибке. Вместо этого просто используйте спецификацию fields , например a/b .

  • Используйте дополнительный селектор, чтобы запросить набор определенных подполей массивов или объектов, помещая выражения в круглые скобки " ( ) ".

    Например: fields=items(id,author/email) возвращает только идентификатор элемента и адрес электронной почты автора для каждого элемента массива элементов. Вы также можете указать одно подполе, где fields=items(id) эквивалентны fields=items/id .

  • При необходимости используйте подстановочные знаки при выборе полей.

    Например: fields=items/pagemap/* выбирает все объекты в карте страниц.

Дополнительные примеры использования параметра полей

В приведенных ниже примерах описано, как значение параметра fields влияет на ответ.

Примечание. Как и все значения параметров запроса, значение параметра fields должно быть закодировано в URL-адресе. Для лучшей читаемости в примерах в этом документе кодировка не указана.

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

Вот несколько примеров на уровне коллекции:
Примеры Эффект
items Возвращает все элементы массива items, включая все поля в каждом элементе, но не другие поля.
etag,items Возвращает поле etag и все элементы массива items.
items/title Возвращает только поле title для всех элементов массива элементов.

Всякий раз, когда возвращается вложенное поле, ответ включает в себя включающие его родительские объекты. Родительские поля не включают в себя другие дочерние поля, если они также не выбраны явно.
context/facets/label Возвращает только поле label для всех членов массива facets , который сам вложен в объект context .
items/pagemap/*/title Для каждого элемента массива items возвращает только поле title (если оно присутствует) всех объектов, которые являются дочерними элементами pagemap .

Вот несколько примеров на уровне ресурсов:
Примеры Эффект
title Возвращает поле title запрошенного ресурса.
author/uri Возвращает подполе uri объекта author в запрошенном ресурсе.
links/*/href
Возвращает поле href всех объектов, являющихся дочерними элементами links .
Запрашивайте только части определенных полей, используя подвыборки .
По умолчанию, если в вашем запросе указаны определенные поля, сервер возвращает объекты или элементы массива целиком. Вы можете указать ответ, который включает только определенные подполя. Вы делаете это, используя синтаксис подвыбора " ( ) ", как в примере ниже.
Пример Эффект
items(title,author/uri) Возвращает только значения title и uri автора для каждого элемента массива items.

Обработка частичных ответов

После того как сервер обрабатывает действительный запрос, включающий параметр запроса fields , он отправляет обратно код состояния HTTP 200 OK вместе с запрошенными данными. Если параметр запроса fields имеет ошибку или по какой-либо причине недействителен, сервер возвращает код состояния HTTP 400 Bad Request вместе с сообщением об ошибке, сообщающим пользователю, что было неправильно с выбором полей (например, "Invalid field selection a/b" ).

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

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

Частичный ответ выглядит так:

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

Примечание. Для API, которые поддерживают параметры запроса для разбивки данных на страницы (например, maxResults и nextPageToken ), используйте эти параметры, чтобы уменьшить результаты каждого запроса до управляемого размера. В противном случае выигрыш в производительности, возможный при частичном отклике, может быть не реализован.

Патч (частичное обновление)

Вы также можете избежать отправки ненужных данных при изменении ресурсов. Чтобы отправлять обновленные данные только для определенных полей, которые вы меняете, используйте команду HTTP PATCH . Семантика исправлений, описанная в этом документе, отличается (и проще), чем для старой реализации частичного обновления GData.

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

Пример

В этом примере показан простой запрос на исправление для обновления только заголовка общего (вымышленного) ресурса API «Демо». Ресурс также имеет комментарий, набор характеристик, статус и многие другие поля, но этот запрос отправляет только поле title , поскольку это единственное поле, которое модифицируется:

PATCH https://www.googleapis.com/demo/v1/324
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "title": "New title"
}

Ответ:

200 OK
{
  "title": "New title",
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "accuracy": "high",
    "followers": ["Jo", "Will"],
  },
  "status": "active",
  ...
}

Сервер возвращает код состояния 200 OK вместе с полным представлением обновленного ресурса. Поскольку в запрос на исправление было включено только поле title , это единственное значение, которое отличается от предыдущего.

Примечание. Если вы используете параметр fields частичного ответа в сочетании с патчем, вы можете еще больше повысить эффективность запросов на обновление. Запрос на исправление только уменьшает размер запроса. Частичный ответ уменьшает размер ответа. Поэтому, чтобы уменьшить объем данных, отправляемых в обоих направлениях, используйте запрос исправления с параметром fields .

Семантика запроса на исправление

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

  • Добавить: Чтобы добавить поле, которого еще нет, укажите новое поле и его значение.
  • Изменить: Чтобы изменить значение существующего поля, укажите поле и установите для него новое значение.
  • Удалить: Чтобы удалить поле, укажите поле и установите для него значение null . Например, "comment": null . Вы также можете удалить весь объект (если он изменяем), установив для него значение null . Если вы используете клиентскую библиотеку Java API , вместо этого используйте Data.NULL_STRING ; подробности см. в разделе JSON null .

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

Использование патча в цикле чтения-изменения-записи

Будет полезно начать с получения частичного ответа с данными, которые вы хотите изменить. Это особенно важно для ресурсов, использующих ETag, поскольку для успешного обновления ресурса необходимо указать текущее значение ETag в HTTP-заголовке If-Match . После получения данных вы можете изменить значения, которые хотите изменить, и отправить измененное частичное представление обратно с запросом на исправление. Вот пример, в котором предполагается, что демонстрационный ресурс использует ETags:

GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token

Это частичный ответ:

200 OK
{
  "etag": "ETagString"
  "title": "New title"
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "level": "5",
    "followers": ["Jo", "Will"],
  }
}

Следующий запрос на исправление основан на этом ответе. Как показано ниже, он также использует параметр fields для ограничения данных, возвращаемых в ответе на исправление:

PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json
If-Match: "ETagString"
{
  "etag": "ETagString"
  "title": "",                  /* Clear the value of the title by setting it to the empty string. */
  "comment": null,              /* Delete the comment by replacing its value with null. */
  "characteristics": {
    "length": "short",
    "level": "10",              /* Modify the level value. */
    "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */
    "accuracy": "high"          /* Add a new characteristic. */
  },
}

Сервер отвечает кодом состояния HTTP 200 OK и частичным представлением обновленного ресурса:

200 OK
{
  "etag": "newETagString"
  "title": "",                 /* Title is cleared; deleted comment field is missing. */
  "characteristics": {
    "length": "short",
    "level": "10",             /* Value is updated.*/
    "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */
    "accuracy": "high"         /* New characteristic is present. */
  }
}

Создание запроса на исправление напрямую

Для некоторых запросов на исправления вам необходимо основывать их на ранее полученных данных. Например, если вы хотите добавить элемент в массив и не хотите потерять ни один из существующих элементов массива, вы должны сначала получить существующие данные. Аналогично, если API использует ETag, вам необходимо отправить предыдущее значение ETag вместе с вашим запросом, чтобы успешно обновить ресурс.

Примечание. Вы можете использовать HTTP-заголовок "If-Match: *" чтобы принудительно пройти исправление, когда используются ETags. Если вы сделаете это, вам не нужно будет выполнять чтение перед записью.

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

PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "comment": "A new comment",
  "characteristics": {
    "volume": "loud",
    "accuracy": null
  }
}

При этом запросе, если поле комментария имеет существующее значение, новое значение перезаписывает его; в противном случае ему будет присвоено новое значение. Аналогично, если была характеристика объема, ее значение перезаписывается; если нет, то он создается. Поле точности, если оно установлено, удаляется.

Обработка ответа на патч

После обработки действительного запроса на исправление API возвращает код ответа HTTP 200 OK вместе с полным представлением измененного ресурса. Если API использует ETag, сервер обновляет значения ETag при успешной обработке запроса на исправление, как и в случае с PUT .

Запрос на исправление возвращает полное представление ресурса, если только вы не используете параметр fields , чтобы уменьшить объем возвращаемых данных.

Если запрос на исправление приводит к новому состоянию ресурса, которое является синтаксически или семантически недопустимым, сервер возвращает код состояния HTTP 400 Bad Request или 422 Unprocessable Entity , а состояние ресурса остается неизменным. Например, если вы попытаетесь удалить значение обязательного поля, сервер вернет ошибку.

Альтернативная запись, если HTTP-команда PATCH не поддерживается.

Если ваш брандмауэр не разрешает запросы HTTP PATCH , выполните запрос HTTP POST и установите для заголовка переопределения значение PATCH , как показано ниже:

POST https://www.googleapis.com/...
X-HTTP-Method-Override: PATCH
...

Разница между патчем и обновлением

На практике, когда вы отправляете данные для запроса на обновление, использующего команду HTTP PUT , вам нужно отправлять только те поля, которые являются обязательными или необязательными; если вы отправляете значения для полей, установленных сервером, они игнорируются. Хотя это может показаться еще одним способом частичного обновления, у этого подхода есть некоторые ограничения. При обновлениях, в которых используется команда HTTP PUT , запрос завершается неудачей, если вы не указываете обязательные параметры, и очищает ранее установленные данные, если вы не указываете дополнительные параметры.

По этой причине гораздо безопаснее использовать патч. Вы предоставляете данные только для тех полей, которые хотите изменить; поля, которые вы пропускаете, не очищаются. Единственное исключение из этого правила возникает с повторяющимися элементами или массивами: если вы опустите их все, они останутся такими, какие есть; если вы предоставите какой-либо из них, весь набор будет заменен предоставленным вами набором.

,

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

Сжатие с помощью gzip

Простой и удобный способ уменьшить пропускную способность, необходимую для каждого запроса, — включить сжатие gzip. Хотя для распаковки результатов требуется дополнительное время процессора, компромисс с сетевыми затратами обычно делает это весьма выгодным.

Чтобы получить ответ в кодировке gzip, вы должны сделать две вещи: установить заголовок Accept-Encoding и изменить свой пользовательский агент, чтобы он содержал строку gzip . Вот пример правильно сформированных HTTP-заголовков для включения сжатия gzip:

Accept-Encoding: gzip
User-Agent: my program (gzip)

Работа с частичными ресурсами

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

Существует два типа частичных запросов:

  • Частичный ответ : запрос, в котором вы указываете, какие поля включить в ответ (используйте параметр запроса fields ).
  • Исправление : запрос на обновление, при котором вы отправляете только те поля, которые хотите изменить (используйте HTTP-команду PATCH ).

Более подробная информация о выполнении частичных запросов представлена ​​в следующих разделах.

Частичный ответ

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

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

Обратите внимание, что параметр fields влияет только на данные ответа; это не влияет на данные, которые вам нужно отправить, если таковые имеются. Чтобы уменьшить объем данных, отправляемых при изменении ресурсов, используйте запрос на исправление .

Пример

В следующем примере показано использование параметра fields с универсальным (вымышленным) «Демо» API.

Простой запрос: этот HTTP-запрос GET опускает параметр fields и возвращает полный ресурс.

https://www.googleapis.com/demo/v1

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

{
  "kind": "demo",
  ...
  "items": [
  {
    "title": "First title",
    "comment": "First comment.",
    "characteristics": {
      "length": "short",
      "accuracy": "high",
      "followers": ["Jo", "Will"],
    },
    "status": "active",
    ...
  },
  {
    "title": "Second title",
    "comment": "Second comment.",
    "characteristics": {
      "length": "long",
      "accuracy": "medium"
      "followers": [ ],
    },
    "status": "pending",
    ...
  },
  ...
  ]
}

Запрос на частичный ответ: следующий запрос для этого же ресурса использует параметр fields , чтобы значительно уменьшить объем возвращаемых данных.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

Частичный ответ: в ответ на приведенный выше запрос сервер отправляет обратно ответ, который содержит только информацию о типе, а также урезанный массив элементов, который включает только информацию о названии и длине HTML в каждом элементе.

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

Обратите внимание, что ответ представляет собой объект JSON, который включает только выбранные поля и включающие их родительские объекты.

Подробности о форматировании параметра fields рассматриваются далее, а затем более подробная информация о том, что именно возвращается в ответе.

Сводка синтаксиса параметров полей

Формат значения параметра запроса fields во многом основан на синтаксисе XPath. Поддерживаемый синтаксис кратко описан ниже, а дополнительные примеры приведены в следующем разделе.

  • Используйте список, разделенный запятыми, чтобы выбрать несколько полей.
  • Используйте a/b , чтобы выбрать поле b вложенное в поле a ; используйте a/b/c чтобы выбрать поле c вложенное в b .

    Исключение: для ответов API, использующих оболочки «данных», где ответ вложен в объект data , который выглядит как data: { ... } , не включайте « data » в спецификацию fields . Включение объекта данных со спецификацией полей, например data/a/b приводит к ошибке. Вместо этого просто используйте спецификацию fields , например a/b .

  • Используйте дополнительный селектор, чтобы запросить набор определенных подполей массивов или объектов, помещая выражения в круглые скобки " ( ) ".

    Например: fields=items(id,author/email) возвращает только идентификатор элемента и адрес электронной почты автора для каждого элемента массива элементов. Вы также можете указать одно подполе, где fields=items(id) эквивалентны fields=items/id .

  • При необходимости используйте подстановочные знаки при выборе полей.

    Например: fields=items/pagemap/* Выбирает все объекты в PageMap.

Больше примеров использования параметра полей

Примеры ниже включают описания того, как значение параметра fields влияет на ответ.

Примечание. Как и во всех значениях параметров запроса, значение параметра fields должно быть закодировано URL. Для лучшей читаемости примеры в этом документе пропускают кодирование.

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

Вот несколько примеров на уровне коллекции:
Примеры Эффект
items Возвращает все элементы в массиве элементов, включая все поля в каждом элементе, но никаких других полей.
etag,items Возвращает как поле etag , так и все элементы в массиве предметов.
items/title Возвращает только поле title для всех элементов в массиве предметов.

Всякий раз, когда возвращается вложенное поле, ответ включает в себя родительские объекты. Родительские поля не включают никаких других детских полей, если они также не выбраны явно.
context/facets/label Возвращает только поле label для всех членов массива facets , которое само по себе вложено под объект context .
items/pagemap/*/title Для каждого элемента в массиве элементов возвращает только поле title (если присутствует) всех объектов, которые являются детьми pagemap .

Вот несколько примеров уровня ресурсов:
Примеры Эффект
title Возвращает поле title запрошенного ресурса.
author/uri Возвращает подполе uri объекта author в запрошенном ресурсе.
links/*/href
Возвращает поле href всех объектов, которые являются детьми links .
Запросите только части конкретных полей, используя подборы .
По умолчанию, если ваш запрос определяет определенные поля, сервер возвращает объекты или элементы массива полностью. Вы можете указать ответ, который включает только определенные суб-поля. Вы делаете это с помощью « ( ) » синтаксиса подборки, как в примере ниже.
Пример Эффект
items(title,author/uri) Возвращает только значения title и uri автора для каждого элемента в массиве элементов.

Обработка частичных ответов

После того, как сервер обрабатывает допустимый запрос, который включает параметр запроса fields , он отправляет обратный код состояния HTTP 200 OK вместе с запрошенными данными. Если параметр запроса fields имеет ошибку или в противном случае недействителен, сервер возвращает код состояния 400 Bad Request , а также сообщение об ошибке, сообщающее пользователю, что не так с их выбором поля (например, "Invalid field selection a/b" ).

Вот пример частичного ответа, показанный во вводном разделе выше. В запросе используется параметр fields , чтобы указать, какие поля вернуть.

https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)

Частичный ответ выглядит так:

200 OK
{
  "kind": "demo",
  "items": [{
    "title": "First title",
    "characteristics": {
      "length": "short"
    }
  }, {
    "title": "Second title",
    "characteristics": {
      "length": "long"
    }
  },
  ...
  ]
}

ПРИМЕЧАНИЕ. Для API, которые поддерживают параметры запроса для странификации данных (например, maxResults и nextPageToken ), используйте эти параметры, чтобы уменьшить результаты каждого запроса до управляемого размера. В противном случае, производительность, возможная с частичным ответом, может быть не реализована.

Патч (частичное обновление)

Вы также можете избежать отправки ненужных данных при изменении ресурсов. Чтобы отправить обновленные данные только для конкретных полей, которые вы меняете, используйте глагол HTTP PATCH . Семантика патча, описанная в этом документе, отличается (и проще), чем для более старой реализации частичного обновления GDATA.

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

Пример

В этом примере показан простой запрос на патч, чтобы обновить только заголовок общего (вымышленного) «Демо» ресурса API. Ресурс также имеет комментарий, набор характеристик, статус и многие другие области, но этот запрос отправляет только поле title , поскольку это единственное поле, измененное:

PATCH https://www.googleapis.com/demo/v1/324
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "title": "New title"
}

Ответ:

200 OK
{
  "title": "New title",
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "accuracy": "high",
    "followers": ["Jo", "Will"],
  },
  "status": "active",
  ...
}

Сервер возвращает код состояния 200 OK , а также полное представление обновленного ресурса. Поскольку только поле title было включено в запрос на патч, это единственное значение, которое отличается ранее.

ПРИМЕЧАНИЕ. Если вы используете параметр fields частичного отклика в сочетании с патчем, вы можете еще больше повысить эффективность запросов на обновление. Запрос на патч только уменьшает размер запроса. Частичный ответ уменьшает размер ответа. Таким образом, чтобы уменьшить объем данных, отправляемых в обоих направлениях, используйте запрос на патч с параметром fields .

Семантика запроса на патч

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

  • Добавить: Чтобы добавить поле, которое еще не существует, укажите новое поле и его значение.
  • Измените: чтобы изменить значение существующего поля, укажите поле и установите его на новое значение.
  • Удалить: чтобы удалить поле, укажите поле и установите его на null . Например, "comment": null . Вы также можете удалить весь объект (если он изменен), установив его на null . Если вы используете клиентскую библиотеку Java API , вместо этого используйте Data.NULL_STRING ; Для получения подробной информации см. Json Null .

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

Использование патча в цикле «Модификация чтения модификации»

Это может быть полезной практикой для начала с получения частичного ответа с данными, которые вы хотите изменить. Это особенно важно для ресурсов, которые используют ETAGS, поскольку вы должны предоставить текущее значение ETAG в заголовке HTTP If-Match , чтобы успешно обновить ресурс. После того, как вы получите данные, вы можете изменить значения, которые вы хотите изменить, и отправить измененное частичное представление обратно с помощью запроса на патч. Вот пример, который предполагает, что демонстрационный ресурс использует Etags:

GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token

Это частичный ответ:

200 OK
{
  "etag": "ETagString"
  "title": "New title"
  "comment": "First comment.",
  "characteristics": {
    "length": "short",
    "level": "5",
    "followers": ["Jo", "Will"],
  }
}

Следующий запрос на патч основан на этом ответе. Как показано ниже, он также использует параметр fields для ограничения данных, возвращаемых в ответе патча:

PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json
If-Match: "ETagString"
{
  "etag": "ETagString"
  "title": "",                  /* Clear the value of the title by setting it to the empty string. */
  "comment": null,              /* Delete the comment by replacing its value with null. */
  "characteristics": {
    "length": "short",
    "level": "10",              /* Modify the level value. */
    "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */
    "accuracy": "high"          /* Add a new characteristic. */
  },
}

Сервер отвечает с кодом состояния 200 OK и частичным представлением обновленного ресурса:

200 OK
{
  "etag": "newETagString"
  "title": "",                 /* Title is cleared; deleted comment field is missing. */
  "characteristics": {
    "length": "short",
    "level": "10",             /* Value is updated.*/
    "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */
    "accuracy": "high"         /* New characteristic is present. */
  }
}

Напрямую построить запрос на патч

Для некоторых запросов на патч вам необходимо основывать их на данных, которые вы ранее получили. Например, если вы хотите добавить элемент в массив и не хотите потерять ни один из существующих элементов массива, вы должны сначала получить существующие данные. Точно так же, если API использует ETAGS, вам необходимо отправить предыдущее значение ETAG с вашим запросом, чтобы успешно обновить ресурс.

Примечание. Вы можете использовать заголовок "If-Match: *" HTTP, чтобы заставить патч пройти, когда используются ETAG. Если вы сделаете это, вам не нужно читать перед записи.

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

PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics
Authorization: Bearer your_auth_token
Content-Type: application/json

{
  "comment": "A new comment",
  "characteristics": {
    "volume": "loud",
    "accuracy": null
  }
}

С помощью этого запроса, если поле комментариев имеет существующее значение, новое значение перезаписывает его; В противном случае это установлено на новое значение. Точно так же, если была характеристика объема, его значение перезаписано; Если нет, это создано. Поле точности, если установлено, удалено.

Обработка ответа на патч

После обработки допустимого запроса патча API возвращает 200 OK Code http -http вместе с полным представлением модифицированного ресурса. Если ETAGs используются API, сервер обновляет значения ETAG, когда он успешно обрабатывает запрос на патч, как это происходит с PUT .

Запрос патча возвращает все представление ресурса, если вы не используете параметр fields , чтобы уменьшить количество данных, которые он возвращает.

Если запрос на патч приводит к новому состоянию ресурса, которое является синтаксически или семантически недействительным, сервер возвращает 400 Bad Request или 422 Unprocessable Entity кода состояния HTTP, а состояние ресурса остается неизменным. Например, если вы пытаетесь удалить значение для требуемого поля, сервер возвращает ошибку.

Альтернативная нотация, когда патч HTTP -глагол не поддерживается

Если ваш брандмауэр не разрешает запросы HTTP PATCH , то выполните запрос POST HTTP и установите заголовок переопределения в PATCH , как показано ниже:

POST https://www.googleapis.com/...
X-HTTP-Method-Override: PATCH
...

Разница между патчем и обновлением

На практике, когда вы отправляете данные для запроса на обновление, который использует глагол HTTP PUT , вам нужно только отправлять те поля, которые являются либо необходимыми, либо необязательными; Если вы отправляете значения для полей, которые установлены сервером, они игнорируются. Хотя это может показаться еще одним способом сделать частичное обновление, этот подход имеет некоторые ограничения. С помощью обновлений, которые используют PUT HTTP, запрос сбой, если вы не предоставляете требуемые параметры, и он очищает ранее устанавливающие данные, если вы не предоставляете дополнительные параметры.

По этой причине гораздо безопаснее использовать патч. Вы поставляете данные только для поля, которые хотите изменить; Поля, которые вы опускаете, не очищены. Единственное исключение из этого правила происходит с повторяющимися элементами или массивами: если вы опустите их все, они остаются такими, какие они есть; Если вы предоставите какой -либо из них, весь набор заменяется набором, который вы предоставляете.