问题描述
我正在使用不具有批量功能的客户端API(主API)。
我从2个不同的API(客户端API)中获取了数据,并将其合并到一个格式正确的JSON文件中。签入了在线JSON验证程序。
JSON文件是合并的客户数据的1100条记录。一次记录一个记录,我构建了一个函数,可将数据成功提交到主API。
我现在已经构建了一个PHP脚本,该脚本循环遍历JSON文件并获取行数据(每个客户端记录),并将其成功提交给主API。在大约90行之后,PHP脚本超时。
@ini_set('zlib.output_compression',0);
@ini_set('implicit_flush',1);
set_time_limit(600);
@ob_end_clean();
并且正在缓冲每个更新以返回从主API返回的JSON状态代码。
我应该怎么做才能使PHP在大约100条记录后不超时并继续更新页面上的缓冲区响应。?
谢谢。
Jason
解决方法
过去,我对这种问题采取了几种不同的方法。对此的唯一 quick 解决方法是,您是否可以更改服务器上的php.ini设置以增加超时时间,以使批处理完成。这不是一个很好的解决方案,但这是 a 解决方案。
下一个选项(以升序排列)是在浏览器和服务器之间建立循环,在该循环中浏览器发出请求,服务器发送部分记录,然后使用光标指示返回浏览器在此过程结束的情况下,浏览器向服务器发出另一个请求,将游标作为参数发送回去,并一直持续到批处理完成为止。很好,因为您可以向用户显示进度栏。
最后,您可以在服务器上运行一个代理,以等待批处理作业提交并在HTTP请求生命周期之外完全运行它们。因此,您的浏览器会请求启动一个批处理作业,这会在数据库中产生某种记录,从而可以跟踪该作业的状态。代理拾取该作业并将其在工作时设置为挂起状态,然后在完成时设置完成状态。您可以设置一些设置,使您可以定期从浏览器轮询服务器,以便在过程完成时提醒用户。您可以只让代理在批处理完成后向用户发送电子邮件报告。这是最可靠的选择,中断事务的风险最小,并且可以毫不费力地留下审计线索。但是设置起来显然要复杂得多。
,感谢罗布。
您的回复向我指示了正确的方向。
我有点在前端使用您的后端想法。我一次只浏览了20条记录,然后通过javascript刷新了页面,并以21到40等开始。在进度栏中也添加了乐趣。
感谢您帮助我弄清这个主意。这不是正确的方法,但是我的Python和我的PHP一样糟糕。
<?php
@ini_set('zlib.output_compression',0);
@ini_set('implicit_flush',1);
set_time_limit(600);
@ob_end_clean();
require("header.php");
require_once('nav.php');
function sync_systems($sfData){
$dataPost = $sfData;
$postID = $dataPost['ID'];
$epcall = update_profile($dataPost);
$epResult = json_decode($epcall,true);
if($epResult['status'] != 404){
$sfStatus = updateSFOpportunity($epResult['client_id'],$epResult['ep_id'] );
if($sfStatus == 1){
$datamsg = " Success! The sync was a success in both Salesforce and other system. OtherSystem Record " . $epResult['ep_id'] . " was created or updated.<br/>";
} else {
$datamsg = " Success! The sync was a success in other system,but failed in Salesforce<br/>";
}
echo json_encode(['code'=>200,'msg'=>$datamsg]);
} else {
$datamsg = " Failure! The sync did not work.<br/>";
echo json_encode(['code'=>404,'msg'=>$datamsg]);
} // end epResult
}
function sync_ep($sfData){
$dataPost = $sfData;
$postID = $dataPost['ID'];
$epcall = update_profile($dataPost);
$epResult = json_decode($epcall,true);
if($epResult['status'] != 404){
// $sfStatus = updateSFOpportunity($epResult['client_id'],$epResult['ep_id'] );
if($sfStatus == 1){
$datamsg = " Success! The sync was a success in both Salesforce and other system. Other System Record " . $epResult['ep_id'] . " was created or updated.<br/>";
} else {
$datamsg = " Success! The sync was a success in other system,'msg'=>$datamsg]);
} // end epResult
}
$ju = "CustomerData20Fall.json";
//read json file from url in php
$readJSONFile = file_get_contents($ju);
//convert json to array in php
$jfile = json_decode($readJSONFile);
//print_r($jfile);
//convert json to array in php
$epSync = array();
$oldValue = 0;
$total = count($jfile );
?>
<!-- Progress bar holder -->
<div id="progress" style="width:500px;border:1px solid #ccc;"></div>
<!-- Progress information -->
<div id="information" style="width"></div>
<?php
if(isset($_REQUEST["NEXTVALUE"])){
$nextValue = $_REQUEST["NEXTVALUE"];
} else {
$nextValue = 1;
}
$refreshValue = $nextValue + 20;
$displaycounter = $nextValue;
$timeRemaining = 0;
$updatedRecords = 0;
foreach ($jfile as $key => $jsons) {
$newKey = $key;
if($oldValue != $newKey){
if($newKey >= $nextValue && $newKey < $refreshValue){
// echo "Updated: " . [$oldValue]['EPID'] . "<br/>";
// echo "<hr>" . $nextValue . " >= " . $newKey . " < " . $refreshValue;
print_r($epSync[$oldValue]);
$displaycounter = $newKey;
echo sync_systems($epSync[$oldValue]);
usleep(30000);
flush();
} else {
if($key == ($refreshValue)){
$theURL = "sf-ep-sync.php?NEXTVALUE=" . $refreshValue . "&RAND=" . rand();
// echo "<hr>" . $newKey . " = " . $refreshValue . " " . $theURL ."<br/>";
echo "<script>location.href = '" . $theURL . "';</script>";
exit;
}
}
$oldValue = $newKey;
$i = $nextValue + 1;
if(($i + 1) == $total ){
$percent = intval($i/$total * 100)."%";
$timeRemaining = 0;
} else {
$percent = intval($i/$total * 100)."%";
$timeRemaining = (($total - $displaycounter)/60);
}
usleep(30000);
echo '<script language="javascript">
document.getElementById("progress").innerHTML="<div style=\"width:'.$percent.';background-color:#ddd;\"> </div>";
document.getElementById("information").innerHTML="'.$displaycounter.' row(s) of '. $total . ' processed. About ' . round($timeRemaining,2) . ' minutes remaining.";
</script>';
// This is for the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);
}
foreach($jsons as $key => $value) {
$epSync[$newKey][$key] = $value;
}
}
谢谢, 杰森