2016-11-21 160 views
1

我正在運行一個Web應用程序以通過Google API PHP Client Library 2.0.3獲取用戶列表。並將它們保存爲CSV文件,同時我正在屏幕上跟蹤這個過程。我使用的代碼如下:使用Google API的指數退避PHP客戶端庫

$pageToken = null; 
$optParams = array(
    "customer" => "my_customer", 
    "maxResults" => 500, 
    "orderBy" => "email", 
    "sortOrder" => "ASCENDING" 
); 

try { 

    $usernum = 0; 

    do { 

     if ($pageToken){ 
      $optParams['pageToken'] = $pageToken; 
     }   

     $results = $service->users->listUsers($optParams); 
     $pageToken = $results->getNextPageToken(); 
     $users = $results->getUsers(); 

     foreach ($users as $user) { 

      $usernum++; 

      $csvfileusers = array($user->getPrimaryEmail()); 
      fputcsv($savecsv, $csvfileusers); 

      $usersemails = $user->getPrimaryEmail(); 
      print "<li>".$usernum." - <font color='#9dd7fb'>".$usersemails."</font></li>"; 

     } 

    } while($pageToken); 

} catch (Exception $e) { 

    print "An error occurred: " . $e->getMessage(); 

} 

一切工作正常。問題是,我不時得到{ error: { errors: [ { domain: global, reason: backendError, message: Service unavailable. Please try again } ], code: 503, message: Service unavailable. Please try again } }

我知道這意味着我發送請求到Google Server太快,因此我需要實施指數退避解決方案。我的問題是我不知道該怎麼做。有人會提供一個關於如何使用PHP客戶端庫的例子嗎?我知道我可以從長遠的角度弄清楚,但如果我能得到一些幫助,我將不勝感激。

回答

0

因此經過20天的嘗試和調查,並感謝@kyle提供的信息,我想出了這種指數退避解決方案。雖然我不確定這是否是正確的方法,但迄今爲止它一直在爲我工作。這是邏輯...

首先,我需要定義我將重試的錯誤。

$err503ReasonA = "Service unavailable"; // Service unavailable. 
$err503ReasonB = "Backend Error"; //Backend Error 

接下來,我將獲得的用戶,並將它們保存到CSV文件

try { 

    $usernum = 0; 
    $retrynum = 0; 

    do { 

     if ($pageToken){ 
      $optParams['pageToken'] = $pageToken; 
     }   

     $results = $service->users->listUsers($optParams); 
     $pageToken = $results->getNextPageToken(); 
     $users = $results->getUsers(); 

     foreach ($users as $user) { 

      $usernum++; 

      $csvfileusers = array($user->getPrimaryEmail()); 
      fputcsv($savecsv, $csvfileusers); 

      $usersemails = $user->getPrimaryEmail(); 
      print "<li>".$usernum." - <font color='#9dd7fb'>".$usersemails."</font></li>"; 

     } 

    } while($pageToken); 

} 

最後,如果有一個服務器錯誤(5XX),我會嘗試的指數退避的解決方案

catch (Exception $e) { 

    $exception = $e->getMessage(); 

    if(strpos($exception, $err503Reason) !== false){ 

     while($exception != null) { //Exp BackOff 
      $retrynum++; 
      $time = $retrynum * 1; //retrynum * seconds 
      sleep($time); 
      if ($retrynum < 4) { 
       try { 

        do { 

         if ($pageToken){ 
         $optParams['pageToken'] = $pageToken; 
         }   

         $results = $service->users->listUsers($optParams); 
         $pageToken = $results->getNextPageToken(); 
         $users = $results->getUsers(); 

         foreach ($users as $user) { 

         $usernum++; 

         $csvfileusers = array($user->getPrimaryEmail()); 
         fputcsv($savecsv, $csvfileusers); 

         $usersemails = $user->getPrimaryEmail(); 
         print "<li>".$usernum." - <font color='#9dd7fb'>".$usersemails."</font></li>"; 

        } 

        } while($pageToken); 

        $exception = null; 
        $retrynum = 0; 

       } catch (Exception $e) { 
        $exception = $e->getMessage(); 
       } 
      } 
     } 
    } 
} 

我一直在嘗試這個解決方案兩天了,它已經像一個魅力。希望這可能對別人有幫助。我現在很高興。 :)

+0

是否阻止應用程序? – arecaps

+0

@arecaps不像我擔心的那樣。或者「阻止應用程序」是什麼意思? – Morfinismo

1

不幸的是,該文檔是lacking for the actual backoff implementation。但是,Google_Task_Runner類概述了退避實施過程。 You can see how it does it here

但是,根據您的設計,您實際上並不想實施exponential backoff procedure一般的網絡條款。你真的想要扼殺請求,所以你不要抨擊API。根據您迭代的$pageToken的數量,您可以在迭代前進行下一步操作之前執行sleep

另外,$pageToken = $results->getNextPageToken();在一次請求後成爲什麼?因爲你是從響應中設定的,而不是以編程方式減少它,這可能會導致一個無限循環或某種性質。

+0

非常感謝您的意見。我會研究這個並回復你。 – Morfinismo

相關問題