5

我有一个 Web 应用程序,它将对虚拟主机的所有请求重定向到控制器,然后控制器根据 URL 决定要包含和运行哪些文件。有一个通过 POST 接受大型 XML 文件的 Web 服务。我需要应用程序的 memory_limit 和 post_max_ 约为 32M,但接受 XML 的服务除外,这需要它们的限制接近 1024M。 ini_set('memory_limit','1024M')在脚本中工作,但不适用于 post_max_size。

我似乎无法弄清楚该怎么做。我正在尝试类似的事情:

<VirtualHost *:80>
ServerName test.com
DocumentRoot /var/www/test.com/html


php_admin_value include_path .:/var/www/test.com/includes:/var/www/test.com/includes/libs

php_value session.use_only_cookie 1
<Location />
    php_value memory_limit 32M
    php_value post_max_size 30M
    php_value upload_max_filesize 29M
</Location>
<Location /services/big-service>
    php_value memory_limit 1024M
    php_value post_max_size 128M
</Location>

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(.*)$
RewriteCond %{REQUEST_URI} !^/(.*)(html|gif|jpg|png|ico|css|js|dtd|swf|flv|xml)$
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^/(.*)$ /Controller.php/$1 [PT]

</VirtualHost>

所以,通过上面的配置,如果 Controller.php 看起来像

<?php
echo '<pre>';
var_dump(ini_get('memory_limit'));
var_dump(ini_get('post_max_size'));
var_dump(ini_get('upload_max_filesize'));

我会收到 string(3) "32M" string(3) "30M" string(3) "29M"

如果我访问http://test.comhttp://test.com/services/big-service,但我希望看到后面 URL 的更高限制。

是否有人对此有任何不通过 URL 直接使用和访问服务脚本的解决方案?

4

5 回答 5

1

问题是 mod_rewrite 导致它总是转到 /Controller.php,因此永远不会使用带有服务的 Location 块。使用额外的 mod_rewrite 规则

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/services/(.*)$
RewriteCond %{REQUEST_URI} !^/(.*)(html|gif|jpg|png|ico|css|js|dtd|swf|flv|xml)$
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^/(.*)$ /ControllerBig.php/services/$1 [PT]

然后让 ControllerBig 成为 Controller 的克隆

<?php
require_once('Controller.php');

将工作。

编辑:完整的 VirtualHost 块:

<VirtualHost *:80>
ServerName test.com
DocumentRoot /var/www/test.com/html

php_admin_value include_path .:/var/www/test.com/includes:/var/www/test.com/includes/libs

php_value session.use_only_cookie 1
<Location />
    php_value memory_limit 32M
    php_value post_max_size 30M
    php_value upload_max_filesize 29M
</Location>
<Location /services/big-service>
    php_value memory_limit 1024M
    php_value post_max_size 128M
</Location>

RewriteEngine On

RewriteCond %{REQUEST_URI} ^/services/(.*)$
RewriteCond %{REQUEST_URI} !^/(.*)(html|gif|jpg|png|ico|css|js|dtd|swf|flv|xml)$
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^/(.*)$ /ControllerBig.php/services/$1 [PT]

RewriteCond %{REQUEST_URI} ^/(.*)$
RewriteCond %{REQUEST_URI} !^/(.*)(html|gif|jpg|png|ico|css|js|dtd|swf|flv|xml)$
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^/(.*)$ /Controller.php/$1 [PT]

</VirtualHost>
于 2011-05-24T18:05:10.453 回答
0

由于您在运行时决定客户端正在寻找哪个 Web 服务,因此您只能做些什么。您不能使用多个 php.ini 文件,因为一旦 PHP 执行您的脚本,您就会被该实例使用的 .ini 文件困住。

在这种情况下,最好的办法是在 php.ini 中设置更大的限制,然后在脚本中使用 ini_set() 指令来降低该限制。如果这是不可接受的,那么您可以做的最好的事情是仅将 post_max_size 设置为更大的限制,然后在脚本中单独设置每个其他限制。

问题是当 PHP 开始执行你的脚本时,它已经从 php.ini 中读取了它的 post_max_size,并且数据已经被 POST 到你的服务器,所以如果超过这个限制,你的脚本甚至不会执行。

于 2011-05-23T18:56:18.790 回答
0

AFAIK php.ini 是每个 php 实例(php5_module)一个,您可以通过运行其中几个来解决您的问题。

  1. 由于 php5_module 是每个 apache 一个,因此一种解决方案是运行另一个 Apache 实例。问题是它不能在同一个端口 80 中运行

  2. 设置 FCGI 来解析 php 和 php5_module。这样你就可以给每个不同的启动参数。您需要将脚本重命名为 .php 以外的其他内容,以便 fcgi 解析(可能是 .fcgi)

样本

LoadModule fcgid_module modules/mod_fcgid.so  

LoadModule php5_module c:/apps/php/php5apache2_2.dll
AddHandler application/x-httpd-php .php
PHPIniDir "C:/apps/php/ini1"

<IfModule mod_fcgid.c>
AddHandler fcgid-script .fcgi 
FcgidInitialEnv PHPRC "c:/apps/php/ini2"
FcgidWrapper "c:/apps/php/php-cgi.exe" .fcgi
AddType    application/x-httpd-fcgi .fcgi
</IfModule>

但是,不确定此设置的防撞能力如何,呵呵

于 2011-05-23T20:08:50.487 回答
0

您可以设置一个新的基于名称的虚拟主机(因此使用另一个DNS)来处理相同的配置,并对内存限制进行一些更改。

这意味着您的 /services/big-service 的应用程序 url 应该始终使用这个不同的 DNS(并且您的应用程序应该检查这些服务总是取自正确的 url。

php_value 设置可以由 VirtualHost 设置,所以它应该可以工作。如果您检查此表,您会发现 memory_limit 不在 PERDIR 范围内,因此您不能只为目录设置它,只能为完整的 VirtualHost 设置。使用 PERDIR 范围,a<Directory>可能已经能够捕获该东西而不是<Location>(但无论如何,您可能对主 index.php 文件有一个 mod_rewrite,因此它始终是同一个目录)。

使用 2 DNS 解决方案您仍然有一个大问题,您可能会得到一些 apache 进程消耗 1024M 的 RAM,它们稍后将用于更简单的请求,但仍占用此 RAM。所以你必须经常清理你的 apache 孩子(例如 MaxRequestPerChild 到 100)。

即使使用 php-fpm 解决方案的 Fcgid,所以如果没有 mod_php,您的 PHP 脚本也会消耗大量 RAM,这不是最好的做法(您应该测试当 10%/30%/ 时 RAM 会发生什么情况/ 50% 的客户端请求正在使用这些服务,以及您的 php RAM 使用情况如何清理(或不清理)。您应该检查Zend_Memory组件,它也应该可以用作带有 Zend_Cache 元素的库组件,它会为您管理“交换内存缓存”,避免在您的大服务中使用过多的 RAM。

于 2011-05-24T09:50:25.790 回答
0

我怀疑这会奏效。因为,重定向总是转到 Controller.php,我不认为 Apache 将支持基于位置的各种 php.ini 值。

如果 /services/big-service 是一个目录,那么接受 PHP 的值是有意义的,我建议你有一个通用的 php.ini 值或创建一个目录并编写一个 .htaccess 来拥有它自己的 php 设置。

于 2011-05-25T03:55:06.287 回答