Mẹo tăng hiệu suất

Tài liệu này trình bày một số kỹ thuật mà bạn có thể sử dụng để cải thiện hiệu suất của ứng dụng. Trong một số trường hợp, các ví dụ từ những API khác hoặc API chung được dùng để minh hoạ các ý tưởng được trình bày. Tuy nhiên, các khái niệm tương tự cũng áp dụng cho Gmail API.

Nén bằng gzip

Một cách dễ dàng và thuận tiện để giảm băng thông cần thiết cho mỗi yêu cầu là bật tính năng nén gzip. Mặc dù việc này đòi hỏi thêm thời gian CPU để giải nén kết quả, nhưng việc đánh đổi với chi phí mạng thường rất đáng giá.

Để nhận được phản hồi được mã hoá bằng gzip, bạn phải thực hiện 2 việc: Đặt tiêu đề Accept-Encoding và sửa đổi tác nhân người dùng để chứa chuỗi gzip. Sau đây là ví dụ về các tiêu đề HTTP được định dạng đúng cách để bật tính năng nén gzip:

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

Làm việc với các tài nguyên một phần

Một cách khác để cải thiện hiệu suất của các lệnh gọi API là chỉ gửi và nhận phần dữ liệu mà bạn quan tâm. Điều này giúp ứng dụng của bạn tránh chuyển, phân tích cú pháp và lưu trữ các trường không cần thiết, nhờ đó có thể sử dụng các tài nguyên (bao gồm cả mạng, CPU và bộ nhớ) một cách hiệu quả hơn.

Có hai loại yêu cầu một phần:

  • Phản hồi một phần: Yêu cầu mà bạn chỉ định những trường cần đưa vào phản hồi (sử dụng tham số yêu cầu fields).
  • Patch: Yêu cầu cập nhật mà bạn chỉ gửi những trường bạn muốn thay đổi (sử dụng động từ HTTP PATCH).

Bạn có thể xem thêm thông tin chi tiết về cách đưa ra yêu cầu một phần trong các phần sau.

Phản hồi một phần

Theo mặc định, máy chủ sẽ gửi lại toàn bộ thông tin về một tài nguyên sau khi xử lý các yêu cầu. Để có hiệu suất tốt hơn, bạn có thể yêu cầu máy chủ chỉ gửi những trường mà bạn thực sự cần và nhận được phản hồi một phần thay vì toàn bộ.

Để yêu cầu phản hồi một phần, hãy sử dụng tham số yêu cầu fields để chỉ định các trường mà bạn muốn trả về. Bạn có thể sử dụng tham số này với mọi yêu cầu trả về dữ liệu phản hồi.

Xin lưu ý rằng tham số fields chỉ ảnh hưởng đến dữ liệu phản hồi; tham số này không ảnh hưởng đến dữ liệu mà bạn cần gửi (nếu có). Để giảm lượng dữ liệu bạn gửi khi sửa đổi tài nguyên, hãy sử dụng yêu cầu patch.

Ví dụ:

Ví dụ sau đây minh hoạ cách sử dụng tham số fields với một API "Demo" (giả định) chung.

Yêu cầu đơn giản: Yêu cầu HTTP GET này bỏ qua tham số fields và trả về toàn bộ tài nguyên.

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

Phản hồi đầy đủ về tài nguyên: Dữ liệu đầy đủ về tài nguyên bao gồm các trường sau, cùng với nhiều trường khác đã bị bỏ qua để cho ngắn gọn.

{
  "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",
    ...
  },
  ...
  ]
}

Yêu cầu phản hồi một phần: Yêu cầu sau đây cho cùng một tài nguyên này sử dụng tham số fields để giảm đáng kể lượng dữ liệu được trả về.

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

Phản hồi một phần: Để phản hồi yêu cầu ở trên, máy chủ sẽ gửi lại một phản hồi chỉ chứa thông tin về loại cùng với một mảng các mục đã được rút gọn, chỉ bao gồm thông tin về tiêu đề HTML và đặc điểm độ dài trong mỗi mục.

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

Xin lưu ý rằng phản hồi là một đối tượng JSON chỉ bao gồm các trường đã chọn và các đối tượng mẹ bao quanh.

Thông tin chi tiết về cách định dạng tham số fields sẽ được trình bày tiếp theo, sau đó là thông tin chi tiết hơn về chính xác những gì được trả về trong phản hồi.

Tóm tắt cú pháp tham số trường

Định dạng của giá trị tham số yêu cầu fields dựa trên cú pháp XPath. Cú pháp được hỗ trợ được tóm tắt dưới đây và các ví dụ khác được cung cấp trong phần sau.

  • Sử dụng danh sách được phân tách bằng dấu phẩy để chọn nhiều trường.
  • Sử dụng a/b để chọn một trường b được lồng trong trường a; sử dụng a/b/c để chọn một trường c được lồng trong b.

    Trường hợp ngoại lệ: Đối với các phản hồi API sử dụng trình bao bọc "data", trong đó phản hồi được lồng trong một đối tượng data có dạng data: { ... }, đừng thêm "data" vào quy cách fields. Việc đưa đối tượng dữ liệu vào cùng với một quy cách trường như data/a/b sẽ gây ra lỗi. Thay vào đó, chỉ cần sử dụng một quy cách fields như a/b.

  • Sử dụng bộ chọn phụ để yêu cầu một tập hợp các trường phụ cụ thể của mảng hoặc đối tượng bằng cách đặt biểu thức trong dấu ngoặc đơn "( )".

    Ví dụ: fields=items(id,author/email) chỉ trả về mã mặt hàng và email của tác giả cho từng phần tử trong mảng mặt hàng. Bạn cũng có thể chỉ định một trường con duy nhất, trong đó fields=items(id) tương đương với fields=items/id.

  • Sử dụng ký tự đại diện trong lựa chọn trường (nếu cần).

    Ví dụ: fields=items/pagemap/* chọn tất cả các đối tượng trong một sơ đồ trang.

Các ví dụ khác về cách sử dụng tham số fields

Các ví dụ bên dưới bao gồm nội dung mô tả về cách giá trị tham số fields ảnh hưởng đến phản hồi.

Lưu ý: Giống như tất cả các giá trị tham số truy vấn, giá trị tham số fields phải được mã hoá URL. Để dễ đọc hơn, các ví dụ trong tài liệu này sẽ bỏ qua quá trình mã hoá.

Xác định các trường bạn muốn trả về hoặc thực hiện lựa chọn trường.
Giá trị tham số yêu cầu fields là một danh sách các trường được phân tách bằng dấu phẩy và mỗi trường được chỉ định tương ứng với gốc của phản hồi. Do đó, nếu bạn đang thực hiện một thao tác list, thì phản hồi sẽ là một tập hợp và thường bao gồm một mảng tài nguyên. Nếu bạn đang thực hiện một thao tác trả về một tài nguyên duy nhất, các trường sẽ được chỉ định liên quan đến tài nguyên đó. Nếu trường bạn chọn là (hoặc là một phần của) một mảng, thì máy chủ sẽ trả về phần đã chọn của tất cả các phần tử trong mảng.

Dưới đây là một số ví dụ ở cấp bộ sưu tập:
Ví dụ Hiệu quả
items Trả về tất cả các phần tử trong mảng items, bao gồm tất cả các trường trong mỗi phần tử, nhưng không có trường nào khác.
etag,items Trả về cả trường etag và tất cả các phần tử trong mảng items.
items/title Chỉ trả về trường title cho tất cả các phần tử trong mảng items.

Bất cứ khi nào một trường lồng nhau được trả về, phản hồi sẽ bao gồm các đối tượng gốc bao quanh. Các trường mẹ không bao gồm bất kỳ trường con nào khác, trừ phi các trường con đó cũng được chọn một cách rõ ràng.
context/facets/label Chỉ trả về trường label cho tất cả các thành viên của mảng facets. Mảng này được lồng trong đối tượng context.
items/pagemap/*/title Đối với mỗi phần tử trong mảng items, chỉ trả về trường title (nếu có) của tất cả các đối tượng là phần tử con của pagemap.

Dưới đây là một số ví dụ ở cấp tài nguyên:
Ví dụ Hiệu quả
title Trả về trường title của tài nguyên được yêu cầu.
author/uri Trả về trường phụ uri của đối tượng author trong tài nguyên được yêu cầu.
links/*/href
Trả về trường href của tất cả các đối tượng là thành phần con của links.
Chỉ yêu cầu các phần của những trường cụ thể bằng cách sử dụng lựa chọn phụ.
Theo mặc định, nếu yêu cầu của bạn chỉ định các trường cụ thể, thì máy chủ sẽ trả về toàn bộ các đối tượng hoặc phần tử mảng. Bạn có thể chỉ định một phản hồi chỉ bao gồm một số trường phụ nhất định. Bạn thực hiện việc này bằng cách sử dụng cú pháp chọn phụ "( )", như trong ví dụ bên dưới.
Ví dụ: Hiệu quả
items(title,author/uri) Chỉ trả về các giá trị của titleuri của tác giả cho từng phần tử trong mảng items.

Xử lý phản hồi một phần

Sau khi xử lý một yêu cầu hợp lệ có chứa tham số truy vấn fields, máy chủ sẽ gửi lại mã trạng thái HTTP 200 OK, cùng với dữ liệu được yêu cầu. Nếu tham số truy vấn fields có lỗi hoặc không hợp lệ, thì máy chủ sẽ trả về mã trạng thái HTTP 400 Bad Request, cùng với một thông báo lỗi cho người dùng biết vấn đề với lựa chọn trường của họ (ví dụ: "Invalid field selection a/b").

Sau đây là ví dụ về phản hồi một phần được trình bày trong phần giới thiệu ở trên. Yêu cầu này sử dụng tham số fields để chỉ định những trường cần trả về.

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

Phản hồi một phần sẽ có dạng như sau:

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

Lưu ý: Đối với những API hỗ trợ các tham số truy vấn để phân trang dữ liệu (ví dụ: maxResultsnextPageToken), hãy sử dụng các tham số đó để giảm kết quả của mỗi truy vấn xuống một kích thước có thể quản lý. Nếu không, bạn có thể không nhận được mức tăng hiệu suất có thể có khi sử dụng phản hồi một phần.

Bản vá (bản cập nhật một phần)

Bạn cũng có thể tránh gửi dữ liệu không cần thiết khi sửa đổi tài nguyên. Để chỉ gửi dữ liệu mới cho các trường cụ thể mà bạn đang thay đổi, hãy sử dụng động từ HTTP PATCH. Ngữ nghĩa của bản vá được mô tả trong tài liệu này khác (và đơn giản hơn) so với ngữ nghĩa của bản vá trong việc triển khai GData cũ của bản cập nhật một phần.

Ví dụ ngắn dưới đây cho thấy cách sử dụng bản vá giúp giảm thiểu dữ liệu bạn cần gửi để thực hiện một bản cập nhật nhỏ.

Ví dụ:

Ví dụ này minh hoạ một yêu cầu vá đơn giản để chỉ cập nhật tiêu đề của một tài nguyên API "Demo" (giả định) chung. Tài nguyên này cũng có một nhận xét, một bộ đặc điểm, trạng thái và nhiều trường khác, nhưng yêu cầu này chỉ gửi trường title, vì đó là trường duy nhất được sửa đổi:

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

{
  "title": "New title"
}

Phản hồi:

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

Máy chủ sẽ trả về mã trạng thái 200 OK, cùng với toàn bộ thông tin về tài nguyên đã cập nhật. Vì chỉ có trường title được đưa vào yêu cầu vá, nên đó là giá trị duy nhất khác với trước đây.

Lưu ý: Nếu sử dụng tham số phản hồi một phần fields kết hợp với bản vá, bạn có thể tăng hiệu quả của các yêu cầu cập nhật hơn nữa. Yêu cầu vá chỉ làm giảm kích thước của yêu cầu. Phản hồi một phần giúp giảm kích thước của phản hồi. Vì vậy, để giảm lượng dữ liệu được gửi theo cả hai hướng, hãy sử dụng yêu cầu vá bằng tham số fields.

Ngữ nghĩa của yêu cầu vá

Phần nội dung của yêu cầu vá chỉ bao gồm các trường tài nguyên mà bạn muốn sửa đổi. Khi chỉ định một trường, bạn phải thêm mọi đối tượng mẹ bao quanh, giống như các đối tượng mẹ bao quanh được trả về bằng một phản hồi một phần. Dữ liệu đã sửa đổi mà bạn gửi sẽ được hợp nhất vào dữ liệu của đối tượng mẹ (nếu có).

  • Thêm: Để thêm một trường chưa tồn tại, hãy chỉ định trường mới và giá trị của trường đó.
  • Sửa đổi: Để thay đổi giá trị của một trường hiện có, hãy chỉ định trường đó và đặt thành giá trị mới.
  • Xoá: Để xoá một trường, hãy chỉ định trường đó và đặt thành null. Ví dụ: "comment": null. Bạn cũng có thể xoá toàn bộ đối tượng (nếu đối tượng đó có thể thay đổi) bằng cách đặt đối tượng đó thành null. Nếu bạn đang sử dụng Thư viện ứng dụng Java API, hãy sử dụng Data.NULL_STRING thay thế; để biết thông tin chi tiết, hãy xem Giá trị rỗng JSON.

Lưu ý về mảng: Các yêu cầu vá có chứa mảng sẽ thay thế mảng hiện có bằng mảng mà bạn cung cấp. Bạn không thể sửa đổi, thêm hoặc xoá các mục trong một mảng theo từng phần.

Sử dụng bản vá trong chu kỳ đọc-sửa đổi-ghi

Bạn có thể bắt đầu bằng cách truy xuất một phần phản hồi có dữ liệu mà bạn muốn sửa đổi. Đây là một phương pháp hữu ích. Điều này đặc biệt quan trọng đối với những tài nguyên sử dụng ETag, vì bạn phải cung cấp giá trị ETag hiện tại trong tiêu đề HTTP If-Match để cập nhật tài nguyên thành công. Sau khi nhận được dữ liệu, bạn có thể sửa đổi các giá trị mà bạn muốn thay đổi và gửi lại bản trình bày một phần đã sửa đổi bằng một yêu cầu vá. Sau đây là một ví dụ giả định rằng tài nguyên Demo sử dụng ETag:

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

Đây là phản hồi một phần:

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

Yêu cầu vá sau đây dựa trên phản hồi đó. Như minh hoạ bên dưới, phương thức này cũng sử dụng tham số fields để giới hạn dữ liệu được trả về trong phản hồi vá:

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. */
  },
}

Máy chủ phản hồi bằng mã trạng thái HTTP 200 OK và một phần biểu thị của tài nguyên đã cập nhật:

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. */
  }
}

Trực tiếp tạo yêu cầu vá

Đối với một số yêu cầu vá, bạn cần dựa vào dữ liệu mà bạn đã truy xuất trước đó. Ví dụ: nếu muốn thêm một mục vào một mảng và không muốn mất bất kỳ phần tử mảng hiện có nào, trước tiên, bạn phải lấy dữ liệu hiện có. Tương tự, nếu một API sử dụng ETag, bạn cần gửi giá trị ETag trước đó cùng với yêu cầu để cập nhật tài nguyên thành công.

Lưu ý: Bạn có thể dùng tiêu đề HTTP "If-Match: *" để buộc một bản vá phải được thực hiện khi đang dùng ETag.  Nếu làm như vậy, bạn không cần phải đọc trước khi ghi.

Tuy nhiên, đối với các trường hợp khác, bạn có thể tạo trực tiếp yêu cầu vá mà không cần truy xuất dữ liệu hiện có trước. Ví dụ: bạn có thể dễ dàng thiết lập một yêu cầu vá lỗi để cập nhật một trường thành giá trị mới hoặc thêm một trường mới. Dưới đây là ví dụ:

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
  }
}

Với yêu cầu này, nếu trường nhận xét có giá trị hiện tại, thì giá trị mới sẽ ghi đè giá trị đó; nếu không, giá trị mới sẽ được đặt. Tương tự, nếu có đặc điểm về âm lượng, giá trị của đặc điểm đó sẽ bị ghi đè; nếu không, đặc điểm đó sẽ được tạo. Trường độ chính xác sẽ bị xoá nếu được đặt.

Xử lý phản hồi cho bản vá

Sau khi xử lý một yêu cầu vá hợp lệ, API sẽ trả về mã phản hồi HTTP 200 OK cùng với biểu thị đầy đủ của tài nguyên đã sửa đổi. Nếu API sử dụng ETag, thì máy chủ sẽ cập nhật các giá trị ETag khi xử lý thành công một yêu cầu vá, giống như khi xử lý PUT.

Yêu cầu vá sẽ trả về toàn bộ biểu thị tài nguyên, trừ phi bạn sử dụng tham số fields để giảm lượng dữ liệu mà yêu cầu này trả về.

Nếu yêu cầu vá dẫn đến trạng thái tài nguyên mới không hợp lệ về mặt cú pháp hoặc ngữ nghĩa, thì máy chủ sẽ trả về mã trạng thái HTTP 400 Bad Request hoặc 422 Unprocessable Entity và trạng thái tài nguyên vẫn không thay đổi. Ví dụ: nếu bạn cố gắng xoá giá trị của một trường bắt buộc, thì máy chủ sẽ trả về lỗi.

Ký hiệu thay thế khi động từ HTTP PATCH không được hỗ trợ

Nếu tường lửa của bạn không cho phép các yêu cầu HTTP PATCH, hãy thực hiện yêu cầu HTTP POST và đặt tiêu đề ghi đè thành PATCH, như minh hoạ dưới đây:

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

Sự khác biệt giữa bản vá và bản cập nhật

Trên thực tế, khi gửi dữ liệu cho một yêu cầu cập nhật sử dụng động từ HTTP PUT, bạn chỉ cần gửi những trường bắt buộc hoặc không bắt buộc; nếu bạn gửi giá trị cho những trường do máy chủ đặt, thì các giá trị đó sẽ bị bỏ qua. Mặc dù có vẻ như đây là một cách khác để thực hiện bản cập nhật một phần, nhưng phương pháp này có một số hạn chế. Với các bản cập nhật sử dụng động từ HTTP PUT, yêu cầu sẽ không thành công nếu bạn không cung cấp các tham số bắt buộc và yêu cầu sẽ xoá dữ liệu đã đặt trước đó nếu bạn không cung cấp các tham số không bắt buộc.

Vì lý do này, bạn nên sử dụng bản vá. Bạn chỉ cung cấp dữ liệu cho những trường mà bạn muốn thay đổi; những trường mà bạn bỏ qua sẽ không bị xoá. Ngoại lệ duy nhất đối với quy tắc này là các mảng hoặc phần tử lặp lại: Nếu bạn bỏ qua tất cả các phần tử đó, chúng sẽ vẫn giữ nguyên; nếu bạn cung cấp bất kỳ phần tử nào trong số đó, toàn bộ tập hợp sẽ được thay thế bằng tập hợp mà bạn cung cấp.