Yêu cầu theo lô

Tài liệu này cho biết cách gộp nhóm các lệnh gọi API để giảm số lượng kết nối HTTP mà ứng dụng của bạn phải thực hiện.

Tài liệu này trình bày cụ thể về việc thực hiện yêu cầu theo lô bằng cách gửi yêu cầu HTTP. Thay vào đó, nếu bạn đang sử dụng thư viện ứng dụng của Google để gửi yêu cầu hàng loạt, hãy xem tài liệu về thư viện ứng dụng.

Tổng quan

Mỗi kết nối HTTP mà ứng dụng của bạn tạo ra sẽ dẫn đến một mức hao tổn nhất định. API Google Lớp học hỗ trợ tính năng tạo lô để cho phép ứng dụng của bạn đưa nhiều lệnh gọi API vào một yêu cầu HTTP.

Ví dụ về các trường hợp mà bạn nên sử dụng tính năng tạo lô:

  • Truy xuất danh sách cho một số lượng lớn khoá học.
  • Tạo hoặc cập nhật hàng loạt khoá học.
  • Thêm một số lượng lớn danh sách khoá học.
  • Truy xuất danh sách khoá học cho nhiều người dùng.

Trong mỗi trường hợp, thay vì gửi riêng từng lệnh gọi, bạn có thể nhóm chúng lại với nhau thành một yêu cầu HTTP duy nhất. Tất cả các yêu cầu bên trong phải đi tới cùng một Google API.

Bạn chỉ được thực hiện tối đa 50 lệnh gọi trong một yêu cầu theo lô. Nếu bạn cần thực hiện nhiều lệnh gọi hơn số đó, hãy sử dụng nhiều yêu cầu hàng loạt.

Lưu ý: Hệ thống xử lý hàng loạt cho API Google Lớp học sử dụng cú pháp giống như hệ thống xử lý hàng loạt OData, nhưng ngữ nghĩa thì khác.

Chi tiết gói

Yêu cầu hàng loạt bao gồm nhiều lệnh gọi API được kết hợp thành một yêu cầu HTTP. Yêu cầu này có thể được gửi tới batchPath được chỉ định trong tài liệu khám phá API. Đường dẫn mặc định là /batch/api_name/api_version. Phần này mô tả chi tiết cú pháp hàng loạt; ở phần sau, sẽ có ví dụ.

Lưu ý: Một nhóm các yêu cầu n được gộp chung với nhau sẽ tính vào hạn mức sử dụng của bạn dưới dạng các yêu cầu n, chứ không phải dưới dạng một yêu cầu. Yêu cầu hàng loạt được tách thành một nhóm yêu cầu trước khi xử lý.

Định dạng của yêu cầu hàng loạt

Yêu cầu hàng loạt là một yêu cầu HTTP tiêu chuẩn chứa nhiều lệnh gọi API Google Lớp học, sử dụng loại nội dung multipart/mixed. Trong yêu cầu HTTP chính đó, mỗi phần chứa một yêu cầu HTTP lồng nhau.

Mỗi phần bắt đầu bằng tiêu đề HTTP Content-Type: application/http riêng. Tệp này cũng có thể có một tiêu đề Content-ID (không bắt buộc). Tuy nhiên, các tiêu đề phần chỉ ở đó để đánh dấu phần đầu của phần; chúng tách biệt với yêu cầu được lồng. Sau khi máy chủ khám phá yêu cầu hàng loạt thành các yêu cầu riêng biệt, tiêu đề của phần đó sẽ bị bỏ qua.

Phần nội dung của mỗi phần là một yêu cầu HTTP hoàn chỉnh, với động từ, URL, tiêu đề và nội dung riêng. Yêu cầu HTTP chỉ được chứa phần đường dẫn của URL; URL đầy đủ không được phép trong các yêu cầu hàng loạt.

Tiêu đề HTTP cho yêu cầu hàng loạt bên ngoài, ngoại trừ tiêu đề Content- như Content-Type, áp dụng cho mọi yêu cầu trong lô. Nếu bạn chỉ định một tiêu đề HTTP cho trước trong cả yêu cầu bên ngoài và lệnh gọi riêng lẻ, thì giá trị của tiêu đề lệnh gọi riêng lẻ sẽ ghi đè giá trị của tiêu đề của yêu cầu hàng loạt bên ngoài. Tiêu đề của cuộc gọi riêng lẻ chỉ áp dụng cho cuộc gọi đó.

Ví dụ: nếu bạn cung cấp tiêu đề Uỷ quyền cho một lệnh gọi cụ thể, thì tiêu đề đó sẽ chỉ áp dụng cho lệnh gọi đó. Nếu bạn cung cấp tiêu đề Uỷ quyền cho yêu cầu bên ngoài thì tiêu đề đó sẽ được áp dụng cho tất cả các lệnh gọi riêng lẻ trừ khi chúng ghi đè tiêu đề đó bằng tiêu đề Uỷ quyền của chính lệnh gọi đó.

Khi nhận được yêu cầu theo lô, máy chủ sẽ áp dụng tham số truy vấn và tiêu đề của yêu cầu bên ngoài (nếu thích hợp) cho từng phần, sau đó xử lý từng phần như thể đó là một yêu cầu HTTP riêng.

Phản hồi yêu cầu hàng loạt

Phản hồi của máy chủ là một phản hồi HTTP đơn chuẩn có kiểu nội dung multipart/mixed; mỗi phần là phản hồi cho một trong các yêu cầu trong yêu cầu theo lô, theo cùng thứ tự với các yêu cầu.

Giống như các phần trong yêu cầu, mỗi phần phản hồi đều chứa một phản hồi HTTP hoàn chỉnh, bao gồm một mã trạng thái, tiêu đề và nội dung. Và giống như các phần trong yêu cầu, mỗi phần phản hồi đều được đứng sau bằng một tiêu đề Content-Type đánh dấu sự bắt đầu của phần đó.

Nếu một phần cụ thể của yêu cầu có tiêu đề Content-ID, thì phần tương ứng của phản hồi sẽ có tiêu đề Content-ID trùng khớp, có giá trị ban đầu đứng sau chuỗi response-, như trong ví dụ sau.

Lưu ý: Máy chủ có thể thực hiện các lệnh gọi của bạn theo bất kỳ thứ tự nào. Không tin vào việc các chuỗi đó được thực thi theo thứ tự mà bạn đã chỉ định. Nếu muốn đảm bảo rằng hai lệnh gọi xảy ra theo thứ tự nhất định, bạn không thể gửi các lệnh gọi này trong một yêu cầu; thay vào đó, hãy tự gửi lệnh đầu tiên, sau đó đợi phản hồi cho lệnh gọi đầu tiên trước khi gửi lệnh thứ hai.

Ví dụ:

Ví dụ sau đây minh hoạ việc sử dụng tính năng hàng loạt bằng API Google Lớp học.

Ví dụ về yêu cầu hàng loạt

POST https://classroom.googleapis.com/batch HTTP/1.1
Authorization: Bearer your_auth_token
Content-Type: multipart/mixed; boundary=batch_foobarbaz
Content-Length: total_content_length

--batch_foobarbaz
Content-Type: application/http
Content-Transfer-Encoding: binary
MIME-Version: 1.0
Content-ID: <item1:12930812@classroom.example.com>

PATCH /v1/courses/134529639?updateMask=name HTTP/1.1
Content-Type: application/json; charset=UTF-8
Authorization: Bearer your_auth_token

{
  "name": "Course 1"
}
--batch_foobarbaz
Content-Type: application/http
Content-Transfer-Encoding: binary
MIME-Version: 1.0
Content-ID: <item2:12930812@classroom.example.com>

PATCH /v1/courses/134529901?updateMask=section HTTP/1.1
Content-Type: application/json; charset=UTF-8
Authorization: Bearer your_auth_token
{
  "section": "Section 2"
}
--batch_foobarbaz--

Ví dụ về phản hồi hàng loạt

Đây là phản hồi cho yêu cầu mẫu trong phần trước.

HTTP/1.1 200
Content-Length: response_total_content_length
Content-Type: multipart/mixed; boundary=batch_foobarbaz

--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item1:12930812@classroom.example.com>

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

{
  "id": "134529639",
  "name": "Course 1",
  "section": "Section 1",
  "ownerId": "116269102540619633451",
  "creationTime": "2015-06-25T14:23:56.535Z",
  "updateTime": "2015-06-25T14:33:06.583Z",
  "enrollmentCode": "6paeflo",
  "courseState": "PROVISIONED",
  "alternateLink": "http://classroom.google.com/c/MTM0NTI5NjM5"
}
--batch_foobarbaz
Content-Type: application/http
Content-ID: <response-item2:12930812@classroom.example.com>

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

{
  "id": "134529901",
  "name": "Course 1",
  "section": "Section 2",
  "ownerId": "116269102540619633451",
  "creationTime": "2015-06-25T14:23:08.761Z",
  "updateTime": "2015-06-25T14:33:06.490Z",
  "enrollmentCode": "so75ha5",
  "courseState": "PROVISIONED",
  "alternateLink": "http://classroom.google.com/c/MTM0NTI5OTAx"
}
--batch_foobarbaz--

Sử dụng thư viện ứng dụng

Các mã mẫu sau đây minh hoạ cách gửi yêu cầu hàng loạt bằng thư viện ứng dụng API của Google. Hãy xem hướng dẫn bắt đầu nhanh tương ứng để biết thêm thông tin về cách cài đặt và thiết lập thư viện.

.NET

lớp học/snippets/Lớp họcĐoạn mã/BatchAddstudents.cs
using Google;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Classroom.v1;
using Google.Apis.Classroom.v1.Data;
using Google.Apis.Requests;
using Google.Apis.Services;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ClassroomSnippets
{
    // Class to demonstrate the use of Classroom Batch Add Students API
    public class BatchAddStudents
    {
        /// <summary>
        /// Add multiple students in a specified course.
        /// </summary>
        /// <param name="courseId">Id of the course to add students.</param>
        /// <param name="studentEmails">Email address of the students.</param>
        public static void ClassroomBatchAddStudents(string courseId,
            List<string> studentEmails)
        {
            try
            {
                /* Load pre-authorized user credentials from the environment.
                 TODO(developer) - See https://developers.google.com/identity for 
                 guides on implementing OAuth2 for your application. */
                GoogleCredential credential = GoogleCredential.GetApplicationDefault()
                    .CreateScoped(ClassroomService.Scope.ClassroomRosters);

                // Create Classroom API service.
                var service = new ClassroomService(new BaseClientService.Initializer
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Classroom Snippets"
                });

                var batch = new BatchRequest(service, "https://classroom.googleapis.com/batch");
                BatchRequest.OnResponse<Student> callback = (student, error, i, message) =>
                {
                    if (error != null)
                    {
                        Console.WriteLine("Error adding student to the course: {0}", error.Message);
                    }
                    else
                    {
                        Console.WriteLine("User '{0}' was added as a student to the course.",
                            student.Profile.Name.FullName);
                    }
                };
                foreach (var studentEmail in studentEmails)
                {
                    var student = new Student() {UserId = studentEmail};
                    var request = service.Courses.Students.Create(student, courseId);
                    batch.Queue<Student>(request, callback);
                }

                Task.WaitAll(batch.ExecuteAsync());
            }
            catch (Exception e)
            {
                // TODO(developer) - handle error appropriately
                if (e is AggregateException)
                {
                    Console.WriteLine("Credential Not found");
                }
                else if (e is GoogleApiException)
                {
                    Console.WriteLine("Course does not exist.");
                }
                else
                {
                    throw;
                }
            }
        }
    }
}

Java

lớp học/snippets/src/main/java/BatchAddAPIs.java
import com.google.api.client.googleapis.batch.BatchRequest;
import com.google.api.client.googleapis.batch.json.JsonBatchCallback;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonError;
import com.google.api.client.http.HttpHeaders;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.classroom.Classroom;
import com.google.api.services.classroom.ClassroomScopes;
import com.google.api.services.classroom.model.Student;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/* Class to demonstrate the use of Classroom Batch Add Students API */
public class BatchAddStudents {

  /* Scopes required by this API call. If modifying these scopes, delete your previously saved
  tokens/ folder. */
  static ArrayList<String> SCOPES =
      new ArrayList<>(Arrays.asList(ClassroomScopes.CLASSROOM_ROSTERS));

  /**
   * Add multiple students in a specified course.
   *
   * @param courseId - Id of the course to add students.
   * @param studentEmails - Email address of the students.
   * @throws IOException - if credentials file not found.
   * @throws GeneralSecurityException - if a new instance of NetHttpTransport was not created.
   */
  public static void batchAddStudents(String courseId, List<String> studentEmails)
      throws GeneralSecurityException, IOException {

    // Create the classroom API client.
    final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
    Classroom service =
        new Classroom.Builder(
                HTTP_TRANSPORT,
                GsonFactory.getDefaultInstance(),
                ClassroomCredentials.getCredentials(HTTP_TRANSPORT, SCOPES))
            .setApplicationName("Classroom samples")
            .build();

    BatchRequest batch = service.batch();
    JsonBatchCallback<Student> callback =
        new JsonBatchCallback<>() {
          public void onSuccess(Student student, HttpHeaders responseHeaders) {
            System.out.printf(
                "User '%s' was added as a student to the course.\n",
                student.getProfile().getName().getFullName());
          }

          public void onFailure(GoogleJsonError error, HttpHeaders responseHeaders) {
            System.out.printf("Error adding student to the course: %s\n", error.getMessage());
          }
        };
    for (String studentEmail : studentEmails) {
      Student student = new Student().setUserId(studentEmail);
      service.courses().students().create(courseId, student).queue(batch, callback);
    }
    batch.execute();
  }
}

1.199

lớp học/snippets/src/Lớp họcBatchAddAPIs.php
use Google\Client;
use Google\Service\Classroom;
use Google\Service\Classroom\Student;
use Google\Service\Exception;

function batchAddStudents($courseId, $studentEmails)
{
    /* Load pre-authorized user credentials from the environment.
    TODO(developer) - See https://developers.google.com/identity for
     guides on implementing OAuth2 for your application. */
    $client = new Client();
    $client->useApplicationDefaultCredentials();
    $client->addScope("https://www.googleapis.com/auth/classroom.profile.emails");
    $service = new Classroom($client);
    $service->getClient()->setUseBatch(true);
    //create batch
    $batch = $service->createBatch();
    foreach ($studentEmails as $studentEmail) {
        $student = new Student([
            'userId' => $studentEmail
        ]);
        $request = $service->courses_students->create($courseId, $student);
        $requestId = $studentEmail;
        $batch->add($request, $requestId);
    }
    //executing request
    $results = $batch->execute();
    foreach ($results as $responseId => $student) {
        $studentEmail = substr($responseId, strlen('response-') + 1);
        if ($student instanceof Exception) {
            $e = $student;
            printf("Error adding user '%s' to the course: %s\n", $studentEmail,
                $e->getMessage());
        } else {
            printf("User '%s' was added as a student to the course.\n",
                $student->profile->name->fullName, $courseId);
        }
    }
    $service->getClient()->setUseBatch(false);
    return $results;
}

Python

course_id = '123456'
student_emails = ['alice@example.edu', 'bob@example.edu']
def callback(request_id, response, exception):
    if exception is not None:
        print 'Error adding user "{0}" to the course course: {1}'.format(
            request_id, exception)
    else:
        print 'User "{0}" added as a student to the course.'.format(
            response.get('profile').get('name').get('fullName'))
batch = service.new_batch_http_request(callback=callback)
for student_email in student_emails:
    student = {
        'userId': student_email
    }
    request = service.courses().students().create(courseId=course_id,
                                                  body=student)
    batch.add(request, request_id=student_email)
batch.execute(http=http)