Класс PHP Singleton для всех запросов - PullRequest
0 голосов
/ 15 сентября 2011

У меня простая проблема.Я использую php в качестве серверной части и имею вывод html.Мой сайт показывает статус о другом сервере.Итак, процесс выглядит так:

  1. Пользователь браузера переходит на www.example.com/status
  2. Контакты браузера www.example.com/status
  3. Сервер PHP получает запроси запросить информацию о статусе на сайте www.statusserver.com/status
  4. PHP Получает данные, преобразует их в читаемый вывод HTML и отправляет их обратно клиенту
  5. Пользователь браузера может видеть статус.

Итак, я создал одноэлементный класс в php, который получает доступ к серверу статуса всего за 8 секунд.Так что обновляет статус все 8 секунд.Если пользователь запрашивает обновление между ними, сервер возвращает локально (на www.example.com) сохраненное состояние.

Это хорошо, не правда ли?Но потом я сделал простой тест и запустил 5 окон браузера, чтобы посмотреть, работает ли он.Здесь php-сервер создал синглтон-класс для каждого запроса.Итак, теперь 5 Клиентов запрашивают у всех 8 секунд статус на сервере состояний.это означает, что у меня каждые 8 ​​секунд 5 вызовов на сервер состояния вместо одного!

Разве нет возможности предоставить только один экземпляр всем пользователям на сервере apache?Это решило бы проблему, если бы 1000 пользователей подключались к www.example.com/status....

thx для любых подсказок

============================= РЕДАКТИРОВАТЬ:

Я уже использую кэширование на жестком диске:

public function getFile($filename)
{
    $diff = (time()-filemtime($filename));
    //echo "diff:$diff<br/>";
    if($diff>8){
        //echo 'grösser 8<br/>';
        self::updateFile($filename);
    }
    if (is_readable($filename)) {
        try {
            $returnValue = @ImageCreateFromPNG($filename);
            if($returnValue == ''){
                sleep(1);
                return self::getFile($filename);
            }else{
                return $returnValue;    
            }
        } catch (Exception $e){
            sleep(1);
            return self::getFile($filename);
        }
    } else {
        sleep(1);
        return self::getFile($filename);
    }
}

это вызов всинглтон.Я вызываю файл и сохраняю его на жестком диске.но все запросы вызывают его одновременно и начинают запрашивать статус сервера.

Я думаю, что единственным решением было бы отдельное приложение, которое обновляет файл каждые 8 ​​секунд ... Все запросы должны просто прочитать файл и, в любом случае, обновить его.Это может быть отдельный скрипт на Perl или что-то подобное ...

Ответы [ 2 ]

3 голосов
/ 15 сентября 2011

Php-запросы обрабатываются разными процессами, и каждый из них имеет свое состояние, нет никакого резидентного процесса, как в другой среде веб-разработки. Вы должны обрабатывать это поведение непосредственно в своем классе, используя, например, некоторое кэширование.

Метод, который запрашивает состояние сервера, должен иметь эту логику

public function getStatus() {
  if (!$status = $cache->load()) {
    // cache miss
    $status = // do your query here
    $cache->save($status); // store the result in cache
  }
  return $status;
}

Таким образом, только один запрос X извлечет реальный статус. Значение X зависит от конфигурации вашего кэша.

Некоторая библиотека кеша, которую вы можете использовать:

  • APC
  • Memcached
  • Zend_Cache , который является просто оберткой для реальных механизмов кэширования

Или вы можете сохранить результат в текстовом файле и при каждом запросе проверять m_time самого файла и перезаписывать его, если прошло более xx секунд.

Обновление

Ваш код довольно странный, почему все эти sleep звонки? Почему блок try / catch, когда ImageCreateFromPNG не выбрасывает?

Вы задаете другой вопрос, так как php не является сервером приложений и не может сохранять состояние между процессами, ваш подход верен. Я предлагаю вам использовать APC (использует разделяемую память, так что это будет как минимум в 10 раз быстрее, чем чтение файла) для обмена статусами между различными процессами. При таком подходе ваш код может стать

public function getFile($filename)
{
    $latest_update = apc_fetch('latest_update');
    if (false == $latest_update) {
      // cache expired or first request
      apc_store('latest_update', time(), 8); // 8 is the ttl in seconds
      // fetch file here and save on local storage
      self::updateFile($filename);
    }
    // here you can process the file
    return $your_processed_file;
}

При таком подходе код в части if будет выполняться из двух разных процессов, только если процесс заблокирован сразу после строки if, что не должно происходить, поскольку почти атомарная операция.

Более того, если вы хотите убедиться, что вам нужно использовать что-то вроде семафоров , чтобы справиться с этим, но это будет слишком большим решением для такого рода требований.

Наконец, 8 секунд - это небольшой интервал, я бы использовал что-то большее, по крайней мере, 30 секунд, но это зависит от ваших требований.

0 голосов
/ 15 сентября 2011

Насколько я знаю, это невозможно в PHP. Однако вы наверняка можете сериализовать и кэшировать экземпляр объекта.
Проверьте http://php.net/manual/en/language.oop5.serialization.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...