Как 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.
Другие вопросы по тегам