【问题标题】:Is php limiting the output bandwidth? Same data via php 20 times slower than directly via apachephp是否限制了输出带宽?通过 php 的相同数据比直接通过 apache 慢 20 倍
【发布时间】:2013-01-20 22:48:30
【问题描述】:

我有一个我无法处理的奇怪问题。我不知道该怎么办,我已经将php.ini设置为以下内容:

max_execution_time = 120
memory_limit = 1024M
output_buffering = on
compression is turned off

网络服务器闲置率约为 95%,可用内存为 6GB。

我还调整了 apache MPM:

mpm_prefork_module:
StartServers          500
MinSpareServers       500
MaxSpareServers      1000
MaxClients          5500
MaxRequestsPerChild   0

但这一切都无济于事(我也尝试了不同的值)。

我需要每分钟处理大约 3000 个传入的 API 请求。我需要为每个返回大约 50KB。

服务器可以处理该数量的传入请求。我测试了它。它只是不能把所有的数据都扔掉。有一种节流。但是在测试带宽时,我得到了完整的 100MBit。

这是我的问题:

当我通过 apache2 下载静态二进制文件时,我的速度为 12000 KiloByte/sec,所以这几乎是整个 100MBit 连接。

我创建了一个 php 文件来执行所有 API 的工作,但不返回结果。它只是返回一些特定大小的随机数据。现在,我正在从不同的服务器加载具有多个线程(当时为 1000 个)的文件/数据。

现在我检查了服务器每分钟处理多少个请求。我计算了每秒的传输速率。

      0 byte = about 5000
   1000 byte = about 3000 =  50 Kilobyte/sec
  10000 byte = about 1600 = 266 Kilobyte/sec
  50000 byte = about  430 = 358 Kilobyte/sec
 100000 byte = about  337 = 561 Kilobyte/sec
 500000 byte = about   69 = 567 Kilobyte/sec

这表明在不返回数据时,服务器可以处理所需数量的请求(它每分钟可以处理 5000 个,而不是我需要的 3000 个)。当我返回我需要的 50KB 时,我每分钟只收到 430 个请求。我返回随机数据还是真实数据都没有关系,使用真实的 PHP 文件或者只是一个返回一些随机 50KB 数据的虚拟数据。这没有任何区别。

如何解决 php 节流问题?

以下是一些会导致相同限制问题的源代码:

<?
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

for ($i = 0; $i < 50000; $i++) 
{
  echo $chars[rand(0, strlen($chars))];
}
?>

【问题讨论】:

  • 您是否将 Apache 中的一个文件 (~12M) 的下载与 PHP 中的大量小文件 (50K) 的下载进行比较?如果是这样,您应该尝试从 Apache 下载大量小文件的测试,否则您将同时更改两个变量,因此测试不公平。我应该认为对 50K 文件的数百/数千个请求的吞吐量比对大文件的请求要低得多,因为连接有自己的时间开销。
  • 是的,单个文件的下载测试只是为了测试服务器的带宽。为了测试并发连接的数量,我做了另一个测试。
  • @Chris 如果您正在测试静态与动态传输,那么测试是不公平的。在动态传输测试期间您的 CPU 使用率是多少?
  • 我有大约 95% 的空闲和 6GB 的可用内存。我的服务器很无聊,但它不会使用内存或 CPU 量来做某事。

标签: php api apache2


【解决方案1】:

这里可能有几个因素在起作用:

PHP 的开销

即使对于一个只生成一个文件的基本脚本,PHP 也必须初始化它自己。这是有代价的。

内存开销

很有可能,您的 PHP 脚本导致将整个 50KB 的数据复制到内存中(这也有成本)。除非您跳过箍以流式传输结果,否则这很可能会发生。

缓冲

与上述类似,如果您没有对结果进行流式处理/分块 - PHP 必须先将整个数据块加载到内存中,然后再将其发送给请求者。

未知数

PHP 的内部有很多移动部件,如果不剖析和分析您的特定脚本,就对减速的真正位置做出许多假设可能是不安全的。

解决它

像 apache 和 nginx 这样的 Web 服务器已针对提供静态文件进行了很好的优化。让他们这样做;它们将总是比在它们之间引入一个间接层更快。

我对您的具体问题知之甚少,但一般准则:

  • 让 PHP 脚本进行基本处理,然后重定向到您的 Web 服务器直接提供的 URL。
  • 如果您需要安全层;考虑设置一次性 URL 或服务器模块,以快速检查请求者是否具有访问权限(但不必管理流式文件内容)

【讨论】:

  • 补充一点,mod_xsendfile 适合在静态文件前面放置一个授权层:tn123.org/mod_xsendfile
  • @Nevir 我编辑了我的帖子以发布一些代码来重现错误。我遇到了像这样的简单 php 的问题(我将其分解为传输问题)。当您说 apache 处理更好的静态数据时,我可以使用随机文件名将 api 结果写入静态文件。然后将此文件名给用户,并说用户应该进行第二次请求以下载 api 请求的结果。现在 apache 可以将此数据作为静态文件提供。
  • 嗯,你的理想是避免 echo 使用 PHP 的任何内容,而是使用 http_redirect。不过,写入临时文件可能会给您带来麻烦(它需要保留多长时间?您什么时候清理它?等等)
  • 即如果结果数据变化不是很频繁,你应该尝试直接缓存它们,并重定向到缓存。如果数据确实经常更改,那么您需要优化您的 PHP 脚本以尽可能高效地将文件数据流回
  • 我的数据因每个请求而改变。出于这个原因,我可以用随机数据很好地测试它。构建整个 50KB 字符串,然后整体回显它并没有改变任何东西 :( 我真的不知道要优化什么。我发布的 5 行代码遇到了同样的问题。因为每次输出都会改变它非常好和我原来的代码差不多。不知道为什么CPU空闲95%,我有6GB的空闲内存。还有足够的空闲带宽,那么apache/php的问题在哪里?
猜你喜欢
  • 1970-01-01
  • 2012-11-17
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 2012-01-24
  • 2012-01-09
  • 1970-01-01
  • 2019-06-26
相关资源
最近更新 更多