webew
Войти » Регистрация
 
PHP

Конкурентный доступ к файлу потоков сервера Apache

11 июня 2009, 21:27
Автор: 1234ru
Идея такая: требуется картинка, которая должна генерироваться динамически. Создаваться она будет с помощью imagepng(), но делать прямой вывод в браузер неудобно, поэтому придется записывать в файл и потом к этому файлу обращаться в HTML с помощью <img>.
Картинка после использования храниться, видимо, не будет (т.е. будет генерироваться заново каждый раз).
Отсюда возникла идея имя файла делать неизменным - другими словами, каждый раз писать в один и тот же файл, просто переписывая каждый раз его содержимое.

Мне нужно точно знать, что с того момента, как пришел запрос к серверу (точнее, с того момента, как одна из функций записала в файл) и до того, как картинка придет в браузер, контроль над этой картинкой будет внутри одного потока (если я правильно называю). То есть, между очередным обновлением содержимого файла-картинки и отдачей картинки браузеру не влезет соседний поток и не перепишет картинку, пока она еще не ушла предыдущему клиенту.
Как это можно обеспечить?

P.S. Кстати. Желательно этот файл делать в памяти, поскольку на диске он нафиг не нужен. Это как-то можно в апаче делать?
Добавить комментарий
Отображение комментариев: Древовидное | Плоское
NO USERPIC

alextop

По-моему вы сами себе противоречите.
С одной стороны "делать прямой вывод в браузер неудобно" (непонятно, почему), но "Картинка после использования храниться, видимо, не будет", в то же время "Желательно этот файл делать в памяти, поскольку на диске он нафиг не нужен".
Похоже на изобретение капчи :)

Мой совет - пользуйтесь imagepng(). Это удовлетворит все ваши запросы - файл картинки никто не перезапишет во время вывода, т.к. не будет на диске (его по идее даже в памяти может не быть - сразу в поток), имя файла будет неизменным. Для "обращения" к файлу картинки не обязательно сохранять его на диске - укажите в качестве адреса имя скрипта, который выведет эту картинку через imagepng().
Например
<img src="http;//server/script.php"/>

Параметры можно передавть либо в url (тогда, правда, имя картинки будет меняться, если это так важно), либо через переменные сессии или куки.
12.06.2009, 01:05
Ответить

1234ru

Вы просто не знаете специфики задачи.
От капчи отличается количеством динамических данных, на основе которых формируется картинка (массивы из десятков и сотен элементов; короче, это разнообразные графики посещаемости).

Попробую подробнее пояснить.
Имеется скрипт, который генерирует HTML (пусть script.php). Внутри этого же HTML надо подцепить картинку, которая генерится динамически на основе данных из этого скрипта.
Неудобство состоит в том, что в потоке, который она отдает в браузер, не может быть ничего, кроме картинки. Другими словами, если у вас есть скрипт image.php, то он не может отдавать никаких данных (в т.ч. HTML), кроме тела картинки.
Соответственно, при таком подходе script.php должен содержать что-то типа <img src="image.php">. Как я уже неоднократно говорил, image.php должен генерироваться динамически на основе массивов данных из script.php.
Основная проблема - как передать эти данные скрипту image.php
(в GET-параметрах не получится, потому что данных может быть совсем немало; через временную таблицу MySQL не хочу; через сессию и куки тоже не хочу; прибегну к такому только если не будет других вариантов)

Вот я и нашел альтернативное решение: imagepng() вызывать прямо в script.php (иначе откуда она возьмет данные?), но делать ей не вывод в браузер, а создавать файл dynamic_image.php, на который потом давать ссылку в HTML - <img src="dynamic_image.php">.

P.S. А кстати POST-запрос без формы как-нибудь можно послать? (чтобы image.php как-нибудь принял данные из него)
То, что не убивает нас, делает нас инвалидами.
12.06.2009, 02:26
Ответить
NO USERPIC

alextop

Я вижу 2 варианта.
1. Не очень красивый. Если у вас очень много входящих параметров, то script.php делает обсчет всего добра и сохраняет результат куда угодно (база, сериализованный файл, xml файл и т.д.) и передает в image.php один параметр (id записи, имя файла и проч.), а тот в свою очередь строит картинку.
2. Сделать нечто типа механизма кеширования.
script.php рассчитывает все что надо, делает картинку, сохраняет ее на диск и дает ссылку на нее. Изюм состоит в имени картинки - оно является хешем от всех входящих параметров. т.е. нечто типа
$filename = md5(serialize($input_parameters))
Таким же макаром можно сохранять результаты обсчета и читать их при следующем вызове script.php, если совпадут входящие параметры.
Файлы можно хранить не на диске, а к примеру в memcached с малым ttl для агрессивной очистки памяти.
POST из картинки никак не прийдет. Взаимодействие намного быстрее и проще организовать на стороне сервера.
12.06.2009, 02:54
Ответить

1234ru

В общем, понятно. Я и хотел то, что вы в варианте 2 описали за исключением того, что хотел как-то обойтись без memcached для записи в память (видимо, это невозможно, т.к. PHP сам такие вещи, как я понимаю, делать не умеет).
Насчет POST это я действительно зря (че-то я забыл, что этоне внутри сервера :о)
То, что не убивает нас, делает нас инвалидами.
12.06.2009, 03:11
Ответить

1234ru

Придется все-таки от memcached отказаться и остановиться на записи файлов на диск.

Основная проблема в том, что функция imagepng() все же неудобная - она хоть и позволяет записать в файл, но не позволяет записать в переменную. А нужно что-то типа

<?php
// тут делаем картинку
// ...
$m = new Memcached();
$m->addServer('localhost', 11211);
$key = generate_imagename(); // тут делаем более-менее уникальное имя-ключ для картинки
$m->set($key, $imagebody);

// вот переменная $imagebody должна содержать тело картинки - её-то и нет:
// imagepng() не отдает его напрямую, только в браузер или файл, но не в переменную  
?>


Тело картинки можно получить обходным путем, записав сначала в файл, а потом прочитав из него, но в таком виде решение теряет всякий смысл (поскольку как раз была задача обойти даже однократную запись на диск).
То, что не убивает нас, делает нас инвалидами.
14.06.2009, 23:37
Ответить
NO USERPIC

alextop

А кто мешает использовать ob_start() и ob_get_clean()? Т.е.
ob_start();
imagepng($image);
$var = ob_get_clean();

Дальше сохраняйте $var куда надо... Не будет никакой записи на диск...
К стати надо глянуть, может картинка, созданная через imagecreatefrompng и есть бинарные данные, которые хранить можно...
14.06.2009, 23:54
Ответить

1234ru

Цитата:
А кто мешает использовать ob_start() и ob_get_clean()?
Мешало, к сожалению, то, что я про них не знал :0
Теперь не мешает. Спасибо большое за подсказку.

Цитата:
К стати надо глянуть, может картинка, созданная через imagecreatefrompng и есть бинарные данные, которые хранить можно...


Похоже на то. Например, код вида

ob_start();
imagepng($image);
$var = ob_get_clean();
header("Content-type: image/png");
echo $var;

исправно выводит картинку.

В общем, спасибо еще раз - подсказали правильное направление.
То, что не убивает нас, делает нас инвалидами.
15.06.2009, 00:39
Ответить
NO USERPIC

rgbeast

С того момента, как в браузер передастся ссылка на картинку до того момента как браузер запросит эту картинку может пройти любой интервал времени, поэтому постановка задачи некорректна. Блокировать файл в ожидании действий пользователя некорректно, так как в это время может произойти обращение к скрипту других пользователей.
12.06.2009, 02:07
Ответить

1234ru

Цитата:
С того момента, как в браузер передастся ссылка на картинку до того момента как браузер запросит эту картинку может пройти любой интервал времени

Ну, то что это некорректно - неочевидно. Но в общем понято.
Значит, буду генерировать файлы с именами высокой степенью уникальности и чистить директорию кроном.
То, что не убивает нас, делает нас инвалидами.
12.06.2009, 02:36
Ответить
Добавить комментарий
Отображение комментариев: Древовидное | Плоское
© 2008—2017 webew.ru, связаться: x собака webew.ru
Сайт использует Flede и соответствует стандартам WAI-WCAG 1.0 на уровне A.
Rambler's Top100

Реклама: