1 Câu hỏi: Hạn ngạch yêu cầu API của Google Drive được tính như thế nào? 'userRateLimitExceeded' được kích hoạt khi bên dưới hạn ngạch được biết đến

câu hỏi được tạo ra tại Tue, Apr 30, 2019 12:00 AM

Hiện đang tích hợp một dự án với Google Drive bằng cách sử dụng API Drive Thư viện khách cho Java , khi sử dụng Tài khoản dịch vụ để mạo danh người dùng để truy xuất nội dung Drive, userRateLimitExceeded được kích hoạt khi số lượng yêu cầu được báo cáo nằm dưới mức hạn mức được xác định thấp nhất có thể nhìn thấy trong Bảng điều khiển.

Tên miền đang được sử dụng để kiểm tra tích hợp Google Drive hiện có yêu cầu cho mỗi người dùng trên 100 giây hạn ngạch được đặt thành 1000. Trong quá trình chạy chương trình, trong đó Tài khoản dịch vụ được sử dụng để mạo danh người dùng và truy xuất các tệp của nó, máy khách Java tạo ra GoogleJsonResponseException do cách sử dụng , cụ thể là userRateLimitExceeded . Tuy nhiên, mức tăng tối đa của bảng điều khiển được báo cáo là 198 yêu cầu /phút, dưới mức giới hạn đã nói.

Đã thử đặt tham số quotaUser ngẫu nhiên cho mỗi yêu cầu như được nêu chi tiết trong trang giải quyết lỗi nhưng điều này mang lại kết quả tương tự.

Chính sách dự phòng theo cấp số nhân được mô tả trong tài liệu bắt đầu chờ trong 1 giây rồi tăng dần thực sự không giúp được gì nhiều, với các yêu cầu về cơ bản bị lừa sau khi chờ 20, 30 giây khi hạn ngạch tiếp tục được kích hoạt.

Để chẩn đoán điều này, đã tạo một thử nghiệm đơn vị nhỏ cho các tình huống chạy khác nhau, trong đó chúng tôi chạy 1000 tên gọi đơn giản chỉ liệt kê 100 tệp đầu tiên trong khu vực Google Drive nổi tiếng trong miền đã nói bằng cách sử dụng Drive đối tượng.

public class GoogleDriveRequestTest {

    private Drive googleDrive;
    //other class attributes

    @Before
    public void setup() throws Exception {
        //sensitive data 

        final Credential credential = new GoogleCredential.Builder()
                .setTransport(httpTransport)
                .setJsonFactory(JacksonFactory.getDefaultInstance())
                .setServiceAccountId(serviceAccountId)
                .setServiceAccountPrivateKey(gdrivePrivateKey)
                .setServiceAccountScopes(ImmutableSet.of(DriveScopes.DRIVE,
                        DirectoryScopes.ADMIN_DIRECTORY_USER,
                        DirectoryScopes.ADMIN_DIRECTORY_GROUP))
                .setServiceAccountUser(serviceAccountUser)
                .build();

        this.googleDrive = new Drive.Builder(httpTransport, JacksonFactory.getDefaultInstance(), credential)
                .setApplicationName("Google Drive API Load Test")
                .build();

        //other initialization code
    }

    @Test
    public void shouldRequestListOfFilesOverAndOverAgain() {
        Stream<Integer> infiniteStream = Stream.iterate(0, i -> i + 1);

        AtomicInteger requestCounter = new AtomicInteger(1);

        infiniteStream
                .limit(1000)
                .map(i -> new GoogleDriveCallable(requestCounter))
                .parallel()
                .map(executorService::submit)
                .map(execution -> {
                    try {
                        return execution.get();
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                })
                .forEach(triple -> System.out.println("Completed request n " + triple.getMiddle() + " in " + triple.getRight() + " millis on thread " + triple.getLeft()));
    }

    private class GoogleDriveCallable implements Callable<Triple<String, Integer, Long>> {
        private final AtomicInteger requestNumber;

        public GoogleDriveCallable(AtomicInteger requestNumber) {
            this.requestNumber = requestNumber;
        }

        @Override
        public Triple<String, Integer, Long> call() throws Exception {
            try {
                try {
                    StopWatch timeIt = StopWatch.createStarted();
                    googleDrive
                            .files()
                            .list()
                            .setSpaces("drive")
                            .setQuotaUser(UUID.randomUUID().toString())
                            .setFields("nextPageToken, files(id, name, mimeType)")
                            .setPageSize(100)
                            .execute();
                    timeIt.stop();
                    return new ImmutableTriple<>(Thread.currentThread().getName(), requestNumber.getAndIncrement(), timeIt.getTime());
                } catch (GoogleJsonResponseException gjre) {
                    GoogleJsonError.ErrorInfo firstReportedError = gjre.getDetails().getErrors().get(0);
                    if (USER_LIMIT_QUOTA_EXCEEDED_ERROR_REASON.equals(firstReportedError.getReason())) {
                        fail("Google user rate limit triggered during request n " + requestNumber);
                    } else {
                        throw gjre;
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException("BOOM during request n " + requestNumber, e);
            }
            return null;
        }
    }
}

Chạy thử nghiệm đơn vị này với số lượng luồng khác nhau (chênh lệch tối thiểu 5 phút giữa các lần chạy để đảm bảo không có nhiễu) mang lại những điều sau:

  • 1 chủ đề
    • tất cả 1000 yêu cầu đều được thực hiện
      • thời gian tối thiểu: 6m49 giây (trung bình 2,44 yêu cầu mỗi giây - > 244 yêu cầu mỗi 100 giây)
      • thời gian tối đa: 7m52s (trung bình 2,12 yêu cầu mỗi giây - > 212 yêu cầu mỗi 100 giây)
  • 2 chủ đề
    • tất cả 1000 yêu cầu đều được thực hiện
      • thời gian tối thiểu: 3m36 giây (trung bình 4,63 yêu cầu mỗi giây - > 463 yêu cầu mỗi 100 giây)
      • thời gian tối đa: 3m46s (trung bình 4,42 yêu cầu mỗi giây - > 438 yêu cầu mỗi 100 giây)
  • 3 chủ đề
    • tất cả 1000 yêu cầu đều được thực hiện
      • thời gian tối thiểu: 2m30 giây (trung bình 6,67 yêu cầu mỗi giây - > 667 yêu cầu mỗi 100 giây)
      • thời gian tối đa: 2m31s (trung bình 6,62 yêu cầu mỗi giây - > 662 yêu cầu mỗi 100 giây)
  • 4 chủ đề
    • thời gian tối thiểu: 11 giây (trung bình 8,27 yêu cầu mỗi giây - > 827 yêu cầu mỗi 100 giây) với userRateLimitExceeded được kích hoạt sau khoảng 91 yêu cầu
    • thời gian tối đa: 40 giây (trung bình 8,75 yêu cầu mỗi giây - > 875 yêu cầu mỗi 100 giây) với userRateLimitExceeded được kích hoạt sau khoảng 350 yêu cầu
  • 5 chủ đề
    • thời gian tối thiểu: 4s (trung bình 8,75 yêu cầu mỗi giây - > 875 yêu cầu mỗi 100 giây) với userRateLimitExceeded được kích hoạt sau khoảng 35 yêu cầu
    • thời gian tối đa: 7 giây (trung bình 9,57 yêu cầu mỗi giây - > 957 yêu cầu mỗi 100 giây) với userRateLimitExceeded được kích hoạt sau khoảng 67 yêu cầu

Đã xác nhận rằng không có ai khác đang sử dụng tên miền nên không có gì phải can thiệp vào các thử nghiệm này.

Tại sao hai kịch bản cuối cùng đó sẽ thất bại khi hạn ngạch của người dùng được kích hoạt nếu chúng tôi không đạt được mốc thời gian 100 giây và, ngay cả khi ngoại suy tốc độ thành 100 giây và chúng vẫn tiến gần, chúng vẫn thiếu 1000 yêu cầu mỗi người dùng trên 100 hạn ngạch?

    
2
1 Đáp án                              1                         

Giao tiếp với bộ phận hỗ trợ của Google đã nhấn mạnh rằng, ngoài hạn ngạch đã biết, các dịch vụ phụ trợ có bảo vệ chống vỡ.

Như vậy, nếu tốc độ yêu cầu không đổi, hạn ngạch sẽ được áp dụng, nhưng trong trường hợp tỷ lệ yêu cầu bị vỡ và cho biết các vụ nổ, nếu ngoại suy như lưu lượng truy cập bình thường, sẽ khiến hạn ngạch bị tràn ngập, API sẽ trả lời lỗi .

    
0
2019-05-14 17: 15: 07Z
nguồn đặt đây