【发布时间】:2013-02-20 03:58:33
【问题描述】:
我正在使用 Webhostingpad 托管一个网站,但遇到了问题。当我的主页加载时,我目前正在对返回用于主页的内容的 php 脚本进行 8 次并发 ajax 调用。 8 个 ajax 调用正在调用一个名为 run.php 的文件。这个文件的工作只是从一个名为 amazon 的类中调用一个函数,该类在另一个名为 amazon.php 的文件中定义。
这是通过 ajax 调用 8 次的 URL。 8 个调用之间的唯一区别是查询字符串:
如您所见,我在 url 的“f”参数中传递函数名称。
run.php 文件如下所示:
require_once('amazon.php');
$function_name = $_REQUEST['f'];
$arg_parameter = $_REQUEST['arg'];
$arg_tmp = explode(";", $arg_parameter);
$arg_array = array();
foreach($arg_tmp as $key_value_pair){
$exploded = explode(':', $key_value_pair);
$key = $exploded[0];
$value = $exploded[1];
$arg_array[$key] = $value;
}
$amazon = new amazon();
echo $amazon->$function_name($arg_array);
如您所见,这个文件只是从 amazon.php 调用一个函数并回显结果,因此我可以在 ajax 函数的回调中使用它。
这是来自 amazon.php 关于getItemsById() 函数的相关代码:
class amazon {
private $url;
private $accessKey = 'AKIAISJ2OHTBA888311SD';
private $secretAccessKey = 'RM8EG61w3dLwjymtAEVdfsdiesd883711lskdf';
function __construct(){
$this->url = 'http://webservices.amazon.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=' . $this->accessKey . '&AssociateTag=global-18&Version=2011-08-01';
}
public function getItemsById($args = array()){
$itemIds = $args['id'];
$url = $this->url;
$url .= '&Operation=ItemLookup';
$url .= '&ItemId=' . $itemIds;
$url .= '&ResponseGroup=Images,Small,Offers,VariationSummary,EditorialReview';
$signedUrl = $this->amazonSign($url, $this->secretAccessKey);
$returned_xml = file_get_contents($signedUrl);
return $returned_xml;
}
}
正如您在上面看到的,此函数正在调用 amazon.com 的 API 的 URL,并使用 PHP 的 file_get_contents() 函数返回 XML。我的问题是对 run.php 进行的一些 ajax 调用已成功执行,而另一些则得到 HTTP 500 内部服务器错误。当我在本地服务器上运行它时,它工作正常。当我在办公室的开发服务器上运行它时,它运行良好。但是,我一直在我的 Webhostingpad 服务器上看到这个问题。一些 ajax 调用返回 HTTP 500 错误。
我已与 Webhostingpad 支持人员交谈过,他们提供给我的唯一见解是我超出了我的 CPU/内存资源限制。来自服务器的错误日志似乎证实了这一点:
[2013 年 2 月 19 日星期二 21:36:39] [错误] [客户端 68.174.126.115] (12)不能 分配内存:无法创建子进程:/opt/suphp/sbin/suphp 对于/home/my-server/public_html/my-domain.com/run.php,推荐人: http://my-domain.com/
我向社区提出的问题是,这里是否有明显的内存密集型问题?我觉得我正在做的事情并没有那么出乎意料,所以我想弄清楚我是否应该专注于优化我的脚本,或者我是否应该只是寻找另一个托管服务提供商。
【问题讨论】:
-
我猜测一台共享服务器上有太多网站。
-
呼叫必须是并发的吗?或者您是否可以简单地执行第一个 AJAX 调用,等到它完成,将本地数据存储在数据结构中,执行第二个调用,冲洗,重复?浏览器中执行 Ajax 调用的对象将在完成后通知您。
-
谢谢@kermit。我以前让 ajax 调用同步工作(我知道这令人不悦,这就是我更改它的原因),但这基本上模仿了您所描述的相同行为,即一个调用仅在另一个调用完成后发生。主要问题是它比同时进行所有 8 个调用并在它们全部完成时使用延迟对象执行操作要慢得多。
-
嗯...另一种选择是在一次 Ajax 调用中发送所有需要的数据,这样只有一个执行 PHP 脚本的实例。为您的类实现单例模式(以便只创建一次实例 - 基本上这涉及一个私有构造函数和一个检查是否创建类的函数。如果是,则返回对该类的引用,如果不是类被构造并返回一个引用)。我认为一次性交易应该减少开销,而不是 8 个单独的调用。
-
Yeesh - 单例模式曾经出现在 PHP.net 网站上,但现在只有德语版本。但是第二个例子——最重要的例子——是用英语写的。不知道那里发生了什么:php.net/manual/de/language.oop5.patterns.php - 暂时不需要担心实现克隆或唤醒方法。这些很好,但不是测试所必需的。
标签: php ajax memory cpu file-get-contents