我正在运行一个网络应用,以获取使用Google API PHP客户端库2.0.3的用户列表。并将它们保存为CSV文件,同时,我正在屏幕上跟踪该过程。我正在使用的代码如下:
$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服务器发送请求的速度太快,因此我需要实施一个指数退避解决方案。我的问题是我不知道该怎么做。有人会非常友好地为我提供一个使用PHP客户端库如何做到这一点的例子吗?我知道我可能能够长期解决这个问题,但如果我能得到一些帮助,我将非常感激。
答案 0 :(得分: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();
在一次请求后会变成什么?因为你是从响应中设置它而不是以编程方式递减它,这可能会导致一个infinute循环或那种性质的东西。
答案 1 :(得分:0)
因此,经过20天的尝试和调查,并感谢@kyle提供的信息,我想出了这个指数退避解决方案。
$attemptNum = 1; // retry attempt
$expBackoff = false; // exponential backoff rety indicator
do {
if($attemptNum <= 4) {
try {
$usernum = 1;
do {
if ($pageToken){
$optParams['pageToken'] = $pageToken;
}
$results = $service->users->listUsers($optParams);
$pageToken = $results->getNextPageToken();
$users = $results->getUsers();
foreach ($users as $user) {
$csvfileusers = array($user->getPrimaryEmail());
fputcsv($savecsv, $csvfileusers);
$usersemails = $user->getPrimaryEmail();
print "<li>".$usernum." - <font color='#9dd7fb'>".$usersemails."</font></li>";
$usernum++;
}
} while($pageToken);
} catch (Exception $e) {
$err503ReasonA = "Service unavailable"; // Service unavailable.
$err503ReasonB = "Backend Error"; //Backend Error
$exception = $e->getMessage();
if(strpos($exception, $err503Reason) !== false || strpos($exception, $err503ReasonB) !== false){
$expBackoff = true;
$sleeptime = $retrynum * 1; //retrynum * seconds
sleep($sleeptime);
$retrynum++;
} else {
$expBackoff = false;
print "There was an error -> $exception";
}
}
} else {
$expBackoff = false;
}
} while ($expBackoff);
我现在已经尝试了这个解决方案两天了,它的工作就像一个魅力。希望这可能对其他人有帮助。我现在很高兴。 :)