Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: PHP: Application server vs ...  (Прочитано 20866 раз)
0 Пользователей и 2 Гостей смотрят эту тему.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 17-04-2012 11:16 » 

Мне нужно реализовать бизнес-приложение клиентов на 100, но с большим мультимедийным трафиком. Основной будет комплекс веб-приложений. Есть ограничение, связанное с квалификацией тех, кто будет заниматься дальнейшей поддержкой. Им предпочтительнее работать только с PHP.

Что меня смущает. Традиционно веб-приложение строится таким образом, что на каждый запрос к серверу происходит обработка некоего скрипта, который запрашивает нужную информацию из БД. Т.е. в процессе обработки запроса по данным из БД восстанавливается вся модель, дальше происходит полезное действие, возможно, обновление данных в БД, формирование ответа, и затем всё теряется. При следующем запросе процесс повторяется. Смущает здесь производительность всей такой технологии.

Частичным решением является использование сессий, но оно по ряду причин неудобно. Сессия уничтожается по таймауту. Таким образом, сессия может рассматриваться как кэш объектов пользователя.

Полным решением будет являться сервер приложений, который способен хранить объектную модель в оперативной памяти в течение всего времени работы. Если такой сервер работает с БД монопольно, количество запросов к БД сокращается до минимума: только запись обновлений объектов. Это бОльшие затраты оперативной памяти, но зато более высокая производительность. При этом выделяют глобальные объекты, общие для всех одновременно работающих пользователей, и локальные для каждого пользователя.

Вопросы:

1) Знает ли кто-нибудь на личном опыте, каковы в эксплуатации серверы приложений, пригодные для написания приложений на PHP?

2) Прошу разъяснить, как nginx снижает нагрузку и ускоряет работу того же Apache. Это происходит только за счёт кэширования пар запрос/ответ, чтобы на одинаковые запросы ответ брался из кэша, а не обрабатывался в общем порядке на Apache? Или же есть что-то ещё?

3) Есть ли у Apache+PHP некая область памяти, аналогичная Application в IIS? (Как сессия, только глобальная для всех сессий, и время жизни которой определяется не сессиями, а активностью всего приложения - т.е. она уничтожается по таймауту, только если приложение полностью бездействует, нет ни одного пользователя.)

4) Любые другие соображения по поводу кэшей, сокращающих обмен по цепочке от браузера до БД.
« Последнее редактирование: 17-04-2012 11:19 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
zubr
Гость
« Ответ #1 : 17-04-2012 11:26 » 

А чем куки не устраивают? В куках, к примеру, можно сохранить дату последнего запроса и тип запроса. Когда клиент обратится к серверу, тот определит, исходя из данных куков, какой объем запроса выполнять.
Записан
Sla
Команда клуба

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 17-04-2012 11:55 » 

смотреть в сторону ускорителей.
например APC
такое решение реализовано на psyradio.com.ua

Запрос к серверу радио сохраняется в кеше информацию о текущем миксе. Опрос сервера радио происходит раз в минуту.
Пользовательские приложения асинхронно обращаются к существующему ключу кеша. Если ключ существует, то контент отдается из мемкеша, если не существует - запрос к серверу радио, и восстановления контента ("ключа") в кеше.


Добавлено через 2 минуты и 39 секунд:
где-то у Ромы есть класс работы с различными ускорителями
« Последнее редактирование: 17-04-2012 11:58 от Sla » Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 17-04-2012 14:55 » 

Цитата: zubr
А чем куки не устраивают? В куках, к примеру, можно сохранить дату последнего запроса и тип запроса. Когда клиент обратится к серверу, тот определит, исходя из данных куков, какой объем запроса выполнять.
Тут главный вопрос: где и каким образом хранить кэш (заранее построенные объекты, предвычисленные значения), чтобы не заниматься перерасчётами и построением объектов на каждое обращение? Cookies на этот вопрос не отвечают.

Ускорители PHP будто-то бы избыточны: в системе будет не более 100 параллельных юзеров (людей, не ботов). Сложных алгоритмов тоже не будет. Самое важное - минимизировать дисковые операции, поскольку основная нагрузка диска будет связана с записью и чтением мультимедийных файлов (аудио-потоки и фотографии). Текстовой информации в БД будет в разы меньше, чем у нас на форуме. Поэтому в идеале хотелось бы такое решение, чтобы все данные "сидели" в оперативной памяти, изменения сбрасывались в БД (и на диск), запросы обрабатывались вообще без обращения к диску.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 17-04-2012 15:31 » 

2. Nginx минимизирует время коммуникации процессов Апача, чем сокращает потребность в их количестве.
Работа самого Nginx почти ничего не стоит. Память расходуется в безумно смешном объеме. На каждый новый сокет используется всего 8 или 16 кБ. Для проксирования контента большего объема используются временные файлы.
Также через Nginx можно настроить отдачу статической составляющей контента, что тоже дает описанный выше эффект.
Кешировать Nginx не умеет, но может взаимодействовать с Memcaсhed: если записи в кеше нет, выполняется запрос к программе; URL используется как ключ.

3. Для каждого запуска PHP-программы интерпретатор создается новый контекст. Т.е. хранение объектов в памяти между запусками невозможно. По этой причине применение FastCGI к PHP не даст повышения производительности.
Shared memory не рекомендую. Лучше пользовательские кеши. Тот же APC подойдет, а если нужно, чтобы копии приложения на нескольких серверах имели общий кеш, то подойдет Memcached (но это на 1-2 порядка медленнее).


Добавлено через 5 минут и 32 секунды:
Объекты поддаются сериализации и результат можно хранить в кеше. Понятное дело, что два параллельных процесса, загрузивших сохраненный объект, создадут у себя два независимых объекта.

Представить себе постоянно работающий процесс PHP я не могу. Просто не знаю, как он будет работать с памятью, есть ли у него проблемы с утечками, хорошо ли работает сборщик мусора. Не для этого PHP разрабатывался, хотя бывает, что на нем и программы пишут.

Добавлено через 6 минут и 44 секунды:
От "ускорителей PHP" рекомендую не отказываться. Это кеш предкомпиленных PHP-файлов. Многократно ускоряет процесс запуска приложения. Тот же APC годится.
Кстати, это тоже сокращает "нагрузку на Апач".
« Последнее редактирование: 17-04-2012 15:43 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 17-04-2012 16:02 » 

Если речь о сериализации, то выгоды у меня не видно. Проще будет из БД каждый раз читать...

А есть ли у кого опыт сборки кластера, когда за одним прокси, балансирующим нагрузку, типа того же nginx, стоит несколько физических серверов с идентичным приложением под Apache? Интересует такое узкое место, как общая БД (на отдельном сервере). Существует какое-нибудь эмпирическое соотношение по времени между обработкой запросов БД и обработкой запросов на Apache (за вычетом времени запросов к БД), при котором кластерное решение становится ощутимо выгоднее?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 17-04-2012 16:32 » 

Такой кластер не может быть выгоднее (в плане времени выполнения отдельного запроса), в сравнении с односерверным решением (приложение, кеши и СУБД на одном сервере).

Эмпирических формул нет. Нагрузочные тесты на конкретном приложении покажут, где у него слабое место.
Заранее можно разве что прикинуть пиковое количество запросов, которое надо будет обработать за некий период.

Добавлено через 41 минуту и 37 секунд:
Основной способ ускорения - кеширование чего-либо, чтобы уменьшить число обращений к СУБД или программной обработки. Тут важно согласование изменения БД и удаления зависимых записей в кеше.

Например, club.shelek.ru: первая страница требует около 300 мс для полной генерации всех фрагментов страницы, но благодаря кешированию большинство запросов обслуживаются за 3 мс.
« Последнее редактирование: 17-04-2012 17:17 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #7 : 17-04-2012 18:25 » 

RXL, тогда так спрошу. Как реализуются кластеры с параллельными идентичными серверами, чтобы при этом, несмотря на параллельную обработку разных пользователей разными серверами, актуальные данные системы оставались бы доступными для всех серверов и всех новых пользователей?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 17-04-2012 18:42 » 

Логично, должны быть общие хранилища данных.
СУБД общая - это понятно.
Если использовать какой-либо кеш, то он тоже должен быть общий, сетевой. Тот же Memcached.

Схема Nginx+Apache+СУБД+Кеш может работать как на одном сервере, так и распределено. От конкретных СУБД и кеш можно абстрагироваться через прослойки: PDO для СУБД и своя прослойка для кеша.

(click to show)
Можно немного упростить, т.к. тут включена поддержка PHP 4 и 5, а также есть устаревшие системы кеширования.

Код: (PHP)
<?php

// (c) 2008 Veselchak U

class Cache
{
    var $_cache_type = 'auto'; // дефолтное значение
    var $_memcache = null;

    function __constructor($options = null)
    {
        $this->Cache($options);
    }

    function Cache($options = null)
    {
        // Проверка поддержки кеш-систем
        $cache_systems = array();

        if (function_exists('eaccelerator_get'))
            $cache_systems[] = 'eaccelerator';

        if (function_exists('apc_fetch'))
            $cache_systems[] = 'apc';

        if (function_exists('xcache_get'))
            $cache_systems[] = 'xcache';

        if (class_exists('Memcache'))
            $cache_systems[] = 'memcache';

        $required_cache = isset($options['cache']) ? $options['cache'] : $this->_cache_type;

        if (count($cache_systems) && $required_cache != 'none')
        {
            if ($required_cache == 'auto')
                $this->_cache_type = array_shift($cache_systems); // первое значение в списке
            else if (in_array($required_cache, $cache_systems))
                $this->_cache_type = $required_cache;
            else
                $this->_cache_type = 'none';
        }
        else
            $this->_cache_type = 'none';

        if ($this->_cache_type == 'memcache')
        {
            $failed = true;

            if (isset($options['memcache']) && is_array($options['memcache']))
            {
                $this->_memcache = new Memcache;

                foreach ($options['memcache'] as $server)
                {
                    if (!is_array($server) || !isset($server['host'])) // host должен быть указан
                        continue;

                    $server['port'] = isset($server['port']) ? (int) $server['port'] : ini_get('memcache.default_port');
                    $server['persistent'] = isset($server['persistent']) ? (bool) $server['persistent'] : true;

                    if ($this->_memcache->addServer($server['host'], $server['port'], $server['persistent']))
                        $failed = false;
                }

                if ($failed)
                    $this->_memcache = null;
            }

            if ($failed)
                $this->_cache_type = 'none';
        }

#       echo "<!--\n", print_r($this, true), "\n-->";
   }

    function get($key)
    {
        $data = null;

        switch ($this->_cache_type)
        {
            case 'none':
                break;
            case 'eaccelerator':
                $data = eaccelerator_get($key);
                break;
            case 'apc':
                $data = apc_fetch($key);
                break;
            case 'xcache':
                $data = xcache_get($key);
                break;
            case 'memcache':
                $data = $this->_memcache->get($key);
                break;
        }

        $data = ($data === false) ? null : $data;

//      $data = null;
        return $data;
    }

    function put($key, &$data, $ttl)
    {
        switch ($this->_cache_type)
        {
            case 'none':
                break;
            case 'eaccelerator':
                eaccelerator_put($key, $data, $ttl);
                break;
            case 'apc':
                apc_store($key, $data, $ttl);
                break;
            case 'xcache':
                xcache_set($key, $data, $ttl);
                break;
            case 'memcache':
                // Решение set() проблемы с несколькими серверами.
                // http://www.php.net/manual/ru/function.memcache-set.php#84032
                if (!$this->_memcache->replace($key, $data, MEMCACHE_COMPRESSED, $ttl))
                    $this->_memcache->set($key, $data, MEMCACHE_COMPRESSED, $ttl);

                break;
        }
    }
}

?>

Дим, я думаю надо от архитектуры исходить, можно ли тут что-то оптимизировать и будет ли это выгоднее классических решений.
« Последнее редактирование: 17-04-2012 18:46 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 17-04-2012 20:30 » 

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

Почитал про memcache... Собственно почти это я и подразумевал в качестве основной функции сервера приложений. Но, как я понял, хранить он будет только сериализованные данные, которые по сети передаются - это скверно. Лучше бы всю объектную модель с бизнес-логикой держать в памяти без (де-)сериализации.

P.S. "А можно 7 шапок?.." (c)
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 18-04-2012 03:47 » 

Если тебя волнует скорость сериализации/десериализации, то уверю, что это очень быстро.

Если очень хочется чтобы все в памяти, рассмотри Ruby on Rails.


Хочу указать на единственное существенное отличие использования Nginx как бекпрокси: клиентский IP, естественно, меняется на IP сервера с Ngnix и по этому, обычно, реальный IP Ngnix помещает в HTTP-заголовок X-Real-IP.
« Последнее редактирование: 18-04-2012 03:53 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 18-04-2012 05:33 » 

Ещё такая мысль появилась. Защитить питание сервера UPS-ом, сделать RAMDisk, положить в него файл БД и так работать. В случае отключения внешнего питания завершать работу и сбрасывать содержимое RAMDisk на жёсткий диск. Будто бы на первый взгляд это по надёжности ничем не хуже обычного решения с базой на жёстком диске, каковой тоже может отказать. Опять же, нагрузка на жёсткий диск сводится к минимуму.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #12 : 18-04-2012 06:20 » new

Dimka, ты не первый до этого додумался. У этого решения огромный минус - надежность. Креш СУБД означает вероятную потерю данных, а креш ОС - гарантированную. По этому промышленно его применяют к распределенным кластерным базам. Некоторые запускают на рам-диске обычные базы, копируя их туда перед запуском. Безответственно это.

Ставь нормальную СУБД, ставь много памяти (благо это самый дешевый компонент) и приставь на первое время админа для мониторинга, анализа и оптимизации. Практически любая СУБД быстро работает при выборке по PK. Частые выборки находятся в кеше СУБД. Значит достаточное количество памяти под кеш.

Проект будет коммерческий? Софт только бесплатный или допустимо применять платный?
Какой объем хранимых данных с СУБД предполагается? Какой рост базы планируется?
Какие прогнозы нагрузки? Сколько запросов в минуту предполагается? Какая задержка ответа допустима?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #13 : 18-04-2012 12:26 » 

Цитата: RXL
Проект будет коммерческий? Софт только бесплатный или допустимо применять платный?
Какой объем хранимых данных с СУБД предполагается? Какой рост базы планируется?
Какие прогнозы нагрузки? Сколько запросов в минуту предполагается? Какая задержка ответа допустима?
1) Да.
2) Да, недопустимо.
3) Оперативная база с историей не более 3-х лет, только короткие текстовые и числовые данные, потолок 6 млн записей. Думаю, в несколько десятков Мб это влезет.
4) До 5 тыс записей в сутки.
5) До 100 параллельных юзеров. Основная нагрузка - всевозможные поиски по разным комбинациям атрибутов по всем записям и отчёты.
6) Думаю, потолок среднего - 100 запросов в минуту, при этом большая дисперсия.
7) Запросы бывают 3-х категориий:
а) запросы на формирование подсказок при вводе пользователем (всякие выпадающие списки а ля Гугл) - тут задержка минимальная, менее секунды, и это самые частые запросы (много полей в формах ввода, зависимости между полями);
б) запросы на формирование результатов поиска и на обновление данных - тут задержка стандартная для GUI 3-5 секунд, запросы пореже;
в) запросы на построение отчётов - тут допустимы задержки до часа, но желательно не более нескольких минут, очень редкие запросы.

В основном для запросов категории а) мне и хочется минимизировать накладные расходы, и разгрузить от них диск. Но структура данных будет представлять собой сеть взаимосвязанных групп записей/объектов, и хорошо бы её хранить в памяти в виде готовых объектов, нежели каждый раз восстанавливать из табличных представлений, или оперировать сериями вспомогательных запросов. Запросы остальных категорий в каком-то особом кэшировании не нуждаются.

Цитата: RXL
Безответственно это.
Crash СУБД или ОС - это риск. Защищаются от него бэкапами, если система работает не в режиме 24х7. В чём здесь более высокая безответственность по сравнению с традиционным решением? RAM менее надёжна, чем HDD, если защита от сбоя в питании гарантирована?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 18-04-2012 16:08 » 

Если у тебя база readonly для пользователей, то можно и из бекапа восстановить. Если же есть онлайн обновления, то при креше потеряешь вплоть до предыдущего бекапа. Конечно у различных СУБД есть механизмы логов для восстановления бекапа до актуального состояния, но их все равно надо писать на диск. Объем описанной базы предполагаю в пару сотен МБ данных и столько же индексов — это легко влезет в кеш СУБД. Производительность же прежде всего зависит от архитектуры базы, построения запросов и продуманности индексов. Такая небольшая база быстро окажется в кеше, но если индексы непродуманны, то поиск все равно будет медленный.

Запросы типа 7a лучше выполнять после ввода хотя бы двух символов, иначе узким местом может оказаться протокол обмена или сам клиент. У меня так было с VB-клиентом: сервер с базой отработали мигом, протокол немного медленнее за счет сериализации/десериализации данных (XMLRPC), а наполнения выпадающего списка 3.5 тыс. строк длится около трех секунд.


Добавлено через 14 минут и 33 секунды:
RAM менее надёжна, чем HDD, если защита от сбоя в питании гарантирована?

Креш современного диска во-первых прогнозируемый, во-вторых предотвращаемый введением избыточности. Программы куда менее надежны.
« Последнее редактирование: 18-04-2012 16:24 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #15 : 18-04-2012 16:58 » 

Цитата: RXL
Производительность же прежде всего зависит от архитектуры базы, построения запросов и продуманности индексов. Такая небольшая база быстро окажется в кеше, но если индексы непродуманны, то поиск все равно будет медленный.
Ну это само собой.

Цитата: RXL
Запросы типа 7a лучше выполнять после ввода хотя бы двух символов, иначе узким местом может оказаться протокол обмена или сам клиент. У меня так было с VB-клиентом: сервер с базой отработали мигом, протокол немного медленнее за счет сериализации/десериализации данных (XMLRPC), а наполнения выпадающего списка 3.5 тыс. строк длится около трех секунд.
Я лично считаю, что combobox с 3.5 тысячами позиций - это форменное издевательство над пользователем Улыбаюсь Оптимально до 9 вариантов.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 18-04-2012 18:00 » 

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

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
zubr
Гость
« Ответ #17 : 19-04-2012 03:01 » 

Цитата
Я лично считаю, что combobox с 3.5 тысячами позиций - это форменное издевательство над пользователем Улыбаюсь Оптимально до 9 вариантов.
Это на любителя. У меня был заказчик (БД по недвижимости), который требовал такую фичу и чтобы не тормозила. Пришлось городить свое всплывающее окно с порционными выборками по мере скроллинга.
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines