Как Apache спулирует STDOUT из CGI-скрипта?
Как часть системы управления контентом, которую я разрабатываю, у меня есть скрипт, который извлекает файлы изображений (JPEG, GIF, PNG и т. Д.) В ответ на браузер, получая URL-адрес, например http://myserver/getimage.cgi/virtual/path/to/image
, На сервере файлы изображений хранятся вне DOCUMENT_ROOT в виде случайно названных больших двоичных объектов, а база данных отслеживает метаданные, в частности соответствие между виртуальным путем, именем файла BLOB-объекта и типом MIME. Сценарий выглядит так:
#!/usr/bin/perl
use CGI::Simple;
use File::Copy;
use MYSTUFF 'dblookup';
my $q = new CGI::Simple;
my ($mimetype, $filepath) = dblookup($q->path_info);
$| = 1; # enable autoflush so header is output before calling copy()
print $q->header(-type=>$mimetype);
copy($filepath, \*STDOUT);
dblookup
Функция экспортируется в MYSTUFF.pm и извлекает mimetype и filepath для виртуального пути, передаваемого через стандартную переменную среды CGI $PATH_INFO.
Меня беспокоит то, как вывод сценария CGI буферизируется сервером Apache, прежде чем он начинает отправлять его обратно в браузер. Если он спулирует весь вывод, то потенциально на сервере требуется огромное количество спулинга, потому что файлы изображений могут иметь размер 10 или 100 МБ, а когда я начинаю поддерживать видеофайлы, они могут достигать ГБ.
Достаточно ли разумен сервер Apache для того, чтобы спулировать поток STDOUT из сценария CGI только до точки, в которой он получил все заголовки (т. Е. Первый "\n\n", который генерируется $q->header()
), а затем начать копирование буфера данных для буфера из STDOUT в любой сокет, подключенный к HTTP-соединению обратно в браузер? Документация для File::Copy предполагает, что он будет использовать буфер размером 1 КБ, поэтому, если Apache ведет себя так, как я обрисовал, у меня, на самом деле, нет проблем, так как сокеты / каналы IPC будут обеспечивать управление потоком на моем сценарии CGI, устраняя необходимость в каком-либо дополнительном пространстве буфера за пределами буферов, которые уже есть??
1 ответ
Я не уверен, как Apache справляется с этим. Однако, если вы спрашиваете об этом по соображениям производительности, то мне интересно, почему вы используете CGI для начала...
Несколько альтернатив, которые вы могли бы рассмотреть:
- Поместите файлы в корень вашего документа, используйте
mod_negotiate
выбрать правильный тип MIME на основе конфигурации на стороне сервера и клиента - использование
mod_rewrite
попросить Apache прочитать конкретный файл в ответ на конкретный запрос. Здесь можно варьировать полученный результат на основании, например, файлов cookie или других вещей, установленных запросом; для получения более подробной информации смотрите документацию mod_rewrite - Если ваш скрипт делает больше, чем просто чтение файла с диска, и ни один из двух приведенных выше вариантов не работает, взгляните на http://mojolicious.org/ для современного веб-фреймворка Perl, который не требует CGI.