13

我有一系列手机号码,大约 50,000 个。我正在尝试使用第三方 API 处理并向这些号码发送批量短信,但浏览器会冻结几分钟。我正在寻找更好的选择。

数据处理包括检查手机号码类型(例如 CDMA)、为所有号码分配唯一 ID 以供进一步参考、检查网络/国家/地区的唯一费用等。

我想过在数据库中排队数据并使用cron每分钟批量发送大约5k,但是如果有很多消息,那将需要时间。我还有哪些其他选择?

我在 XAMPP 服务器上使用 Codeigniter 2。

4

4 回答 4

38

我会写两个脚本:

文件index.php

<iframe src="job.php" frameborder="0" scrolling="no" width="1" height="1"></iframe>
<script type="text/javascript">
    function progress(percent){
        document.getElementById('done').innerHTML=percent+'%';
    }
</script><div id="done">0%</div>

文件job.php

set_time_limit(0);                   // ignore php timeout
ignore_user_abort(true);             // keep on going even if user pulls the plug*
while(ob_get_level())ob_end_clean(); // remove output buffers
ob_implicit_flush(true);             // output stuff directly
// * This absolutely depends on whether you want the user to stop the process
//   or not. For example: You might create a stop button in index.php like so:
//     <a href="javascript:window.frames[0].location='';">Stop!</a>
//     <a href="javascript:window.frames[0].location='job.php';">Start</a>
// But of course, you will need that line of code commented out for this feature to work.

function progress($percent){
    echo '<script type="text/javascript">parent.progress('.$percent.');</script>';
}

$total=count($mobiles);
echo '<!DOCTYPE html><html><head></head><body>'; // webkit hotfix
foreach($mobiles as $i=>$mobile){
    // send sms
    progress($i/$total*100);
}
progress(100);
echo '</body></html>'; // webkit hotfix
于 2011-04-03T23:21:34.730 回答
1

如果这不是一次性的情况,请考虑设计一个更好的解决方案。

你基本上想要的是一个你的浏览器绑定进程可以写入的队列,而不是 1-N 个工作进程可以读取和更新。

将工作放入队列应该相当便宜——也许是一堆简单的 INSERT 语句到 SQL RDBMS。

然后,您可以拥有一个或两个(或 100 个,分布在多个服务器上)从队列中读取并处理内容的守护程序。您需要在这里小心并避免两个工人承担相同的任务,但这并不难编写代码。

所以你的浏览器绑定的工作流程是:点击一些按钮,导致一堆东西被添加到队列中,然后重定向到一些“队列状态”界面,用户可以在其中观看系统浏览他们所有的工作。

像这样的系统很好,因为它很容易水平扩展。

编辑:Christian Sciberras 的回答正朝着这个方向发展,除了浏览器最终驱动双方(它添加到队列中,然后驱动工作进程)

于 2011-04-04T03:39:11.533 回答
1

我假设这些数字在数据库中,如果是这样,您应该添加一个名为 isSent 的新列(或任何您喜欢的)。

您键入的下一段应该排队,并且可能在晚上/每周/适当的时候完成。除非您也有特定原因,否则不应按需批量完成。您甚至可以在数据库中添加一列以查看上次检查的时间,这样如果至少 X 天没有检查某个号码,那么您可以按需对该号码进行检查。

数据处理包括检查手机号码类型(例如 CDMA)、为所有号码分配唯一 ID 以供进一步参考、检查网络/国家/地区的唯一费用等。

但这仍然会让你回到同一个问题,即如何一次处理 50,000 个数字。既然您提到了 cron 作业,我假设您可以通过 SSH 访问您的服务器,这意味着您不需要浏览器。这些 cron 作业可以通过命令行执行,如下所示:

/usr/bin/php /home/用户名/example.com/myscript.php

我的建议是通过 cron 每 10 分钟一次处理 1,000 个数字,并计算这需要多长时间,然后将其保存到数据库中。由于您使用的是 cron 作业,因此这些似乎不是对时间敏感的 SMS 消息,因此它们可以分散开来。一旦您知道此脚本运行 50 次(50*1000 = 50k)需要多长时间,您就可以更新您的 cron 作业以增加/减少运行频率。

$time_start = microtime(true);
set_time_limit(0);

function doSendSMS($phoneNum, $msg, $blah);

$time_end = microtime(true);
$time = $time_end - $time_start;
saveTimeRequiredToSendMessagesInDB($time);

此外,您可能已经注意到 set_time_limit(0),这将告诉 PHP 在默认 30 秒后不超时。如果您能够修改 PHP.ini 文件,则无需输入这行代码。即使您能够编辑 PHP.ini 文件,我仍然建议您不要更改此功能,因为您可能希望其他页面超时。

http://php.net/manual/en/function.set-time-limit.php

于 2011-04-04T00:36:58.290 回答
0

Cronjob 将是您最好的选择,如果您目前唯一的问题是浏览器超时,我不明白为什么它会比在浏览器中执行更长的时间。

如果您坚持通过浏览器执行此操作,则另一种解决方案是以 1000 个批次执行此操作并重定向到相同的脚本,但会参考 $_GET 变量中上次到达的位置。

于 2011-04-04T01:43:20.400 回答