Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Слежение за потреблением ресурсов 
V
    Опции темы
MoLeX
Дата 21.10.2013, 06:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140



Добрый день.

В последнее время на сервере стала ложиться БД на 20-30 секунд, причем происходит это в разное время и в режиме online я не могу выловить причину.

Есть подозрение что в этом виноват один из доброй сотни cron-скриптов, но метод перебора виновника (отключили – проверили, включили) – это не наш случай (простой не позволителен).

Так вот, сам вопрос – как можно собрать логи (для дальнейшего анализа) по использованным ресурсом с адресом скрипта и какие ресурсы (а главное сколько) были задействованы?



--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
Vardoulacha
Дата 21.10.2013, 06:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 184
Регистрация: 11.8.2005

Репутация: 7
Всего: 8



А хостер не дает такой информации? Например у Джино есть страница где показаны какие скрипты сколько процессорного времени отъели и также по базе данных sql запросы.
PM MAIL   Вверх
MoLeX
Дата 21.10.2013, 06:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140



Vardoulacha, хостер дает тока железо.

P.S.
Джино, что такое джино  smile  smile 


--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
ksnk
Дата 21.10.2013, 07:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Джино - это бесплатный хостер с php. Вероятно, имелось ввиду, что даже джино такое умеет ;)

Можно включить лог sql сервера для долго выполняющихся запросов. http://dev.mysql.com/doc/refman/5.1/en/query-log.html. не факт, что это сразу поможет, но по времени можно попытаться ассоциировать его с логом выполнения. Обычно, долгие запросы либо имеют проблемы с индексами, либо натыкаются на блокировку в обновляемой таблице и ждут. Либо просто дофига данных. Либо нужно искать специалиста  smile 

Можно на момент очередного "падения" сервера поднять лог и вычислить потенциальных "скриптов-вредителей". Так как лог, обычно, храниться за некоторое время, то, вероятно, не очень сложно набрать статистику по ним уже сейчас.

Потом можно переставить период вызова "вредителей". Получить новый список, провести новый анализ.




--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Vardoulacha
Дата 21.10.2013, 10:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 184
Регистрация: 11.8.2005

Репутация: 7
Всего: 8



Цитата(ksnk @  21.10.2013,  07:46 Найти цитируемый пост)
Джино - это бесплатный хостер с php. Вероятно, имелось ввиду, что даже джино такое умеет ;)

Бесплатный вряд ли такое умеет, я на платном аккаунте jino.ru

А что если в этих скриптах (которые по крону) собрать статистику самостоятельно?

echo "Initial: ".memory_get_usage()." bytes \n";
echo "Peak: ".memory_get_peak_usage()." bytes \n";

$data = getrusage();
echo "User time: ".($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec'] / 1000000);
PM MAIL   Вверх
Fortop
Дата 21.10.2013, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(MoLeX @  21.10.2013,  06:20 Найти цитируемый пост)
Есть подозрение что в этом виноват один из доброй сотни cron-скриптов

Скриптов не мало?


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
MoLeX
Дата 22.10.2013, 05:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140



Цитата(Fortop @  21.10.2013,  19:38 Найти цитируемый пост)
Скриптов не мало? 

неа))) там очень много вычислений происходит, почти на все случае жизни. вычисления долгие (от 10сек до 3 минут) и при каждом запросе пользователя их нельзя использовать, вот приходится это делать по крону и результат кэшировать.


--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
Sanchezzz
Дата 22.10.2013, 06:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1670
Регистрация: 19.11.2006
Где: Voronezh

Репутация: 41
Всего: 60



Профилирование нужно встраивать.
Код

class Profiler {

    /**
     * @var  integer   maximium number of application stats to keep
     */
    public static $rollover = 1000;

    /**
     * @var  array  collected benchmarks
     */
//    protected static $_marks = array();
    public static $_marks = array();

    /**
     * Starts a new benchmark and returns a unique token. The returned token
     * _must_ be used when stopping the benchmark.
     *
     *     $token = Profiler::start('test', 'profiler');
     *
     * @param   string  $group  group name
     * @param   string  $name   benchmark name
     *
     * @return  string
     */
    public static function start($group, $name)
    {
        static $counter = 0;

        // Create a unique token based on the counter
        $token = 'kp/'.base_convert($counter++, 10, 32);

        Profiler::$_marks[$token] = array
        (
            'group'        => strtolower($group),
            'name'         => (string)$name,

            // Start the benchmark
            'start_time'   => microtime(true),
            'start_memory' => memory_get_usage(),

            // Set the stop keys without values
            'stop_time'    => false,
            'stop_memory'  => false,
        );

        return $token;
    }

    /**
     * Stops a benchmark.
     *
     *     Profiler::stop($token);
     *
     * @param   string  $token
     *
     * @return  void
     */
    public static function stop($token)
    {
        // Stop the benchmark
        Profiler::$_marks[$token]['stop_time'] = microtime(true);
        Profiler::$_marks[$token]['stop_memory'] = memory_get_usage();
    }

    /**
     * Deletes a benchmark. If an error occurs during the benchmark, it is
     * recommended to delete the benchmark to prevent statistics from being
     * adversely affected.
     *
     *     Profiler::delete($token);
     *
     * @param   string  $token
     *
     * @return  void
     */
    public static function delete($token)
    {
        // Remove the benchmark
        unset(Profiler::$_marks[$token]);
    }

    /**
     * Returns all the benchmark tokens by group and name as an array.
     *
     *     $groups = Profiler::groups();
     *
     * @return  array
     */
    public static function groups()
    {
        $groups = array();

        foreach (Profiler::$_marks as $token => $mark)
        {
            // Sort the tokens by the group and name
            $groups[$mark['group']][$mark['name']][] = $token;
        }

        return $groups;
    }

    /**
     * Gets the min, max, average and total of a set of tokens as an array.
     *
     *     $stats = Profiler::stats($tokens);
     *
     * @param   array   $tokens profiler tokens
     *
     * @return  array   min, max, average, total
     * @uses    Profiler::total
     */
    public static function stats(array $tokens)
    {
        // Min and max are unknown by default
        $min = $max = array(
            'time'   => null,
            'memory' => null);

        // Total values are always integers
        $total = array(
            'time'   => 0,
            'memory' => 0);

        foreach ($tokens as $token)
        {
            // Get the total time and memory for this benchmark
            list($time, $memory) = Profiler::total($token);

            if ($max['time'] === null OR $time > $max['time'])
            {
                // Set the maximum time
                $max['time'] = $time;
            }

            if ($min['time'] === null OR $time < $min['time'])
            {
                // Set the minimum time
                $min['time'] = $time;
            }

            // Increase the total time
            $total['time'] += $time;

            if ($max['memory'] === null OR $memory > $max['memory'])
            {
                // Set the maximum memory
                $max['memory'] = $memory;
            }

            if ($min['memory'] === null OR $memory < $min['memory'])
            {
                // Set the minimum memory
                $min['memory'] = $memory;
            }

            // Increase the total memory
            $total['memory'] += $memory;
        }

        // Determine the number of tokens
        $count = count($tokens);

        // Determine the averages
        $average = array(
            'time'   => $total['time'] / $count,
            'memory' => $total['memory'] / $count);

        return array(
            'min'     => $min,
            'max'     => $max,
            'total'   => $total,
            'average' => $average);
    }

    /**
     * Gets the min, max, average and total of profiler groups as an array.
     *
     *     $stats = Profiler::group_stats('test');
     *
     * @param   mixed   $groups single group name string, or array with group names; all groups by default
     *
     * @return  array   min, max, average, total
     * @uses    Profiler::groups
     * @uses    Profiler::stats
     */
    public static function group_stats($groups = null)
    {
        // Which groups do we need to calculate stats for?
        $groups = ($groups === null)
            ? Profiler::groups()
            : array_intersect_key(Profiler::groups(), array_flip((array)$groups));

        // All statistics
        $stats = array();

        foreach ($groups as $group => $names)
        {
            foreach ($names as $name => $tokens)
            {
                // Store the stats for each subgroup.
                // We only need the values for "total".
                $_stats = Profiler::stats($tokens);
                $stats[$group][$name] = $_stats['total'];
            }
        }

        // Group stats
        $groups = array();

        foreach ($stats as $group => $names)
        {
            // Min and max are unknown by default
            $groups[$group]['min'] = $groups[$group]['max'] = array(
                'time'   => null,
                'memory' => null);

            // Total values are always integers
            $groups[$group]['total'] = array(
                'time'   => 0,
                'memory' => 0);

            foreach ($names as $total)
            {
                if (!isset($groups[$group]['min']['time']) OR $groups[$group]['min']['time'] > $total['time'])
                {
                    // Set the minimum time
                    $groups[$group]['min']['time'] = $total['time'];
                }
                if (!isset($groups[$group]['min']['memory']) OR $groups[$group]['min']['memory'] > $total['memory'])
                {
                    // Set the minimum memory
                    $groups[$group]['min']['memory'] = $total['memory'];
                }

                if (!isset($groups[$group]['max']['time']) OR $groups[$group]['max']['time'] < $total['time'])
                {
                    // Set the maximum time
                    $groups[$group]['max']['time'] = $total['time'];
                }
                if (!isset($groups[$group]['max']['memory']) OR $groups[$group]['max']['memory'] < $total['memory'])
                {
                    // Set the maximum memory
                    $groups[$group]['max']['memory'] = $total['memory'];
                }

                // Increase the total time and memory
                $groups[$group]['total']['time'] += $total['time'];
                $groups[$group]['total']['memory'] += $total['memory'];
            }

            // Determine the number of names (subgroups)
            $count = count($names);

            // Determine the averages
            $groups[$group]['average']['time'] = $groups[$group]['total']['time'] / $count;
            $groups[$group]['average']['memory'] = $groups[$group]['total']['memory'] / $count;
        }

        return $groups;
    }

    /**
     * Gets the total execution time and memory usage of a benchmark as a list.
     *
     *     list($time, $memory) = Profiler::total($token);
     *
     * @param   string  $token
     *
     * @return  array   execution time, memory
     */
    public static function total($token)
    {
        // Import the benchmark data
        $mark = Profiler::$_marks[$token];

        if ($mark['stop_time'] === false)
        {
            // The benchmark has not been stopped yet
            $mark['stop_time'] = microtime(true);
            $mark['stop_memory'] = memory_get_usage();
        }

        return array
        (
            // Total time in seconds
            $mark['stop_time'] - $mark['start_time'],

            // Amount of memory in bytes
            $mark['stop_memory'] - $mark['start_memory'],
        );
    }

    /**
     * Gets the total application run time and memory usage. Caches the result
     * so that it can be compared between requests.
     *
     *     list($time, $memory) = Profiler::application();
     *
     * @return  array  execution time, memory
     * @uses    Kohana::cache
     */

    public static function application()
    {
        // Load the stats from cache, which is valid for 1 day
//        $stats = Kohana::cache('profiler_application_stats', NULL, 3600 * 24);
        $stats = null;

        if (!is_array($stats) OR $stats['count'] > Profiler::$rollover)
        {
            // Initialize the stats array
            $stats = array(
                'min'   => array(
                    'time'   => null,
                    'memory' => null),
                'max'   => array(
                    'time'   => null,
                    'memory' => null),
                'total' => array(
                    'time'   => null,
                    'memory' => null),
                'count' => 0);
        }

        // Get the application run time
        $time = microtime(true) - KOHANA_START_TIME;

        // Get the total memory usage
        $memory = memory_get_usage() - KOHANA_START_MEMORY;

        // Calculate max time
        if ($stats['max']['time'] === null OR $time > $stats['max']['time'])
        {
            $stats['max']['time'] = $time;
        }

        // Calculate min time
        if ($stats['min']['time'] === null OR $time < $stats['min']['time'])
        {
            $stats['min']['time'] = $time;
        }

        // Add to total time
        $stats['total']['time'] += $time;

        // Calculate max memory
        if ($stats['max']['memory'] === null OR $memory > $stats['max']['memory'])
        {
            $stats['max']['memory'] = $memory;
        }

        // Calculate min memory
        if ($stats['min']['memory'] === null OR $memory < $stats['min']['memory'])
        {
            $stats['min']['memory'] = $memory;
        }

        // Add to total memory
        $stats['total']['memory'] += $memory;

        // Another mark has been added to the stats
        $stats['count']++;

        // Determine the averages
        $stats['average'] = array(
            'time'   => $stats['total']['time'] / $stats['count'],
            'memory' => $stats['total']['memory'] / $stats['count']);

        // Cache the new stats
//        Kohana::cache('profiler_application_stats', $stats);

        // Set the current application execution time and memory
        // Do NOT cache these, they are specific to the current request only
        $stats['current']['time'] = $time;
        $stats['current']['memory'] = $memory;

        // Return the total application run time and memory usage
        return $stats;
    }

} // End Profiler

 
В интереснейших нас местах 
Код

// от 
$bmrk = Profiler::start('Start script', __FILE__);

// много кода...

// до 
Profiler::stop($bmrk); 



Вывод всех брекмачей
Код

<table class="debug" width="100%" cellpadding="2" style="border-spacing:1px;font:11px Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;color:#666666;">
    <tbody>
    <tr>
        <th colspan="3" style="background:black;color:white;"> Общий отчет (Время: с, Память: Кб)</th>
    </tr>
    <tr style="background-color: #ccc;">
        <th>Группа</th>
        <th style="min-width: 100px;">Макс. (с)</th>
        <th>Memory. (kB)</th>
    </tr>
    </tbody>
    <? $stats = Profiler::group_stats(); ?>
    <? $i = 0; ?>
    <? foreach ($stats as $group => $val): ?>

    <tr style="background: <?=(!$i) ? '#FFFFFF' : '#F5F5F5'?>">
        <td><?=$group?></td>
        <td><?=number_format($val['max']['time'], 6)?>&nbsp;s</td>
        <td><?=number_format($val['max']['memory'] / 1024, 4)?>&nbsp;kB</td>
    </tr>
    <? if (++$i > 1) $i = 0; ?>
    <? endforeach ?>
</table>


Ну все это ручное отлавливание да и к тому же это нужно сохранять.

Это сообщение отредактировал(а) Sanchezzz - 22.10.2013, 07:05


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
ksnk
Дата 22.10.2013, 07:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Sanchezzz, Статистика собирает только memory_get_usage? Ну и как это поможет при блокировке базы данных?

Добавлено через 1 минуту и 49 секунд
Sanchezzz, открывающий [ code] потерян


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
Sanchezzz
Дата 22.10.2013, 07:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1670
Регистрация: 19.11.2006
Где: Voronezh

Репутация: 41
Всего: 60



спс, за тег, не знаю как я его не набрал, похмелье  smile 

В целом не как, но если делать замеры по всему скрипту даст хорошую статистику в каких местах тормозит по замеру времени.
Если база упала мы получаем ексепшен, можно и нужно эти эксепшины  отлавливать и записывать.
Любую ошибку в php можно отловить пусть даже через  smile  магию.
Код

function my_handle(){
    $error = error_get_last();
}
register_shutdown_function('my_handle');






--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
Fortop
Дата 22.10.2013, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2200
Регистрация: 13.11.2007
Где: Донецк

Репутация: 20
Всего: 42



Цитата(MoLeX @  22.10.2013,  05:49 Найти цитируемый пост)
неа))) там очень много вычислений происходит, почти на все случае жизни. вычисления долгие (от 10сек до 3 минут)

я как раз об этом.

У тебя нагрузка на БД непрогнозируема. И подвисать может из-за совокупности совпавших по времени кривых (или не кривых, но сложных очень нужных ) запросов.

Сделай некий тестовый запрос. Он должен быть максимально легким, чтобы не нагружать БД.
Но при этом он должен быть подверженным падению БД в те самые 20-30с.

Дальше просто. Вешаешь скрипт, которые каждые 10с выполняет этот запрос (поэтому он должен быть легким).
Контролируешь его задержку. Если он не выдал ответ за 2-3с.
Делаешь show processlist из этого же или параллельного скрипта.

Добавлено через 3 минуты и 4 секунды
Цитата(Sanchezzz @  22.10.2013,  06:45 Найти цитируемый пост)
В интереснейших нас местах 

У него этих мест сотни только в кроне. Плюс сам сайт.

И пользуйтесь xhprof он может работать даже под нагрузкой 80к уников в час - потеряешь не более 20% производительности (для сравнения xdebug сажает производительно в 2-10 раз)

Добавлено через 3 минуты и 46 секунд
Цитата(Sanchezzz @  22.10.2013,  07:17 Найти цитируемый пост)
но если делать замеры по всему скрипту

Pinba все то же, что ты хочешь своим скриптом и насколько я знаю - много больше.


--------------------
Мир это Я.
Живее всех живых.
PM MAIL   Вверх
Sanchezzz
Дата 22.10.2013, 19:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1670
Регистрация: 19.11.2006
Где: Voronezh

Репутация: 41
Всего: 60



Пинба скажет сколько скрипт и всего ресурсов сейчас используется от БД до железа. 

хы это не мой класс стандартный выдрал из коханы.



Это сообщение отредактировал(а) Sanchezzz - 22.10.2013, 19:01


--------------------
Понравился ответ "+" по репе, не забываем закрывать тему, заказы в LS.
PM MAIL Skype GTalk   Вверх
MoLeX
Дата 23.10.2013, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Местный пингвин
****


Профиль
Группа: Модератор
Сообщений: 4076
Регистрация: 17.5.2007

Репутация: 46
Всего: 140



Цитата(Fortop @  22.10.2013,  15:15 Найти цитируемый пост)
Сделай некий тестовый запрос. Он должен быть максимально легким, чтобы не нагружать БД.
Но при этом он должен быть подверженным падению БД в те самые 20-30с.

Дальше просто. Вешаешь скрипт, которые каждые 10с выполняет этот запрос (поэтому он должен быть легким).
Контролируешь его задержку. Если он не выдал ответ за 2-3с.
Делаешь show processlist из этого же или параллельного скрипта.

хм. интересное решение, надо попробовать.

Сейчас удалось точно увидеть что виноват MySQL, причем он уперся не в оперативу а в CPU:
Цитата

PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
18232 mysql     20   0 1288m 820m 7792 S  401  3.4 238:16.44 mysqld




--------------------
Amazing  smile 
PM MAIL WWW ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0655 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.