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

В условиях, когда корректно написанный код не вызывает значительных нагрузок на имеющееся оборудование с избыточными ресурсами, явления подобного рода могут и не привлекать к себе особого внимания. Однако, в не идеальных условиях, такое поведение уже может, каким минимум, отвлекать серверное время и мешать другим клиентам, а как максимум – повлечь финансовые издержки. И если вы считаете для себя преамбулу актуальной, давайте обозначим действия в рамках описанного явления как негативные, а все остальные – пусть будут позитивными.

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

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

Сессия клиента


Сейчас я предположу, что вы наверняка управляете клиентскими сессиями. Так или иначе, нам это потребуется. Как известно, в общем случае, сессия клиента имеет уникальный идентификатор, а также некий набор условных данных, необходимый для менеджмента в рамках индивидуального проекта. Конечно же, очевидно, этот набор данных строго выверен и определен исключительно для ваших потребностей. При грамотном планировании, такие данные кратки, лаконичны и, при этом, имеют более чем одно назначение. Как правило, сессия содержит в себе временной штамп последнего запроса клиента. Это значение служит, в первую очередь, для определения и удаления устаревших сессий, может применяться для определения активности пользователей и для некоторых других функциональных особенностей. Одной из таких особенностей будет реализация нашего функционала. Однако не обойдется и без внедрения новой составляющей. Но, как и было обещано в самом начале, все что нам потребуется – это добавить к вашему набору данных всего один байт. Но об этом чуть позже.

Смысловая нагрузка запроса


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

  1. Время, затраченное клиентом на получение данных от последнего запроса, принятие решения, формирование и отправку следующего запроса;
  2. Уровень доверия к запросам клиента. Как правило, значение этого признака определяет связанность сессии с учетной записью, уровень аккаунта и ему подобное;
  3. Характер запроса: подразумевает ли запрос возможность немедленного ответа от клиента, либо требует осознанного анализа полученных данных для принятия решения;
  4. Эталонная форма поведения клиента для переданного запроса.

Этих сведений вполне достаточно. Теперь нам осталось выразить их в неких числовых представлениях для дальнейшего расчета.

Первый пункт, назовем его «TIME», вычисляется как разница в секундах между текущим временем и временем последнего запроса.

Второй пункт, назовем его «SAFE», условный. Пусть это будет значение в диапазоне от 0 до 5, с возрастанием от гостевой сессии до сессии очень доверенного пользователя.

Третий пункт, пусть будет «AUTO», отвечает на вопрос «ДА» или «НЕТ». Его форма очевидна.

Четвертым пунктом, называемым «NORM», нам необходимо назначить эталонную форму поведения. Поскольку действия клиента в нашем наборе сведений характеризуются временем, то и этот параметр мы будет задавать по временной шкале.

Логика поведения


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

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

Подобное поведение можно выразить через график логарифмической функции.



Таким образом, зная точку отсчета «NORM», для каждой «TIME» мы имеем возможность получения знакового значения, характеризующее наличие или отсутствие смысловой нагрузки в запросе. Отныне будем называть его «RATE».

Приведение в действие


Вычислив значение нагрузки отдельного запроса, определим, носят ли действия пользователя во времени позитивный характер, или же следует ограничить его действия.

Здесь следует заметить, что не всякие, трактуемые как негативные, запросы в совокупности имеют соответствующую окраску. Мы не вправе исключать случаи, когда клиент, посредством ряда коротких запросов стремится достигнуть места размещения интересующей его информации. Именно по этой причине нам необходимо оценивать действия клиента во времени.

С этой целью введем некий счетчик «очков» клиента, назовем его «LOAD». Диапазон значений прекрасно можно уложить в один байт, то есть от 0 до 255. С каждым запросом клиента мы будем прибавлять к нему знаковое значение смысловой нагрузки запроса «RATE». Таким образом, следующие подряд запросы с коротким интервалом значительно увеличат «LOAD», после чего, запросы с длинным интервалом, будут уменьшать это значение.

В том случае, когда поведение клиента явно противоречит хорошему тону, его сессия довольно быстро вырвется в лидеры по параметру «LOAD». И здесь также имеются варианты поведения.

Введем еще два значения: предупреждающее и ограничивающее. При достижении параметра «LOAD» условно «опасного» значения, может быть частично ограничена обработка запросов клиента. Однако, если же интервал запросов не уменьшится, при достижении предельного значения, логичным будет блокировка адреса клиента.

Реализация


Представим примерное хранилище сессий в виде следующей таблицы на диалекте MySQL.

CREATE TABLE `sess_info`
(
  `time` INTEGER UNSIGNED COMMENT 'Session last request time',
  `user` INTEGER UNSIGNED COMMENT 'Session account id',
  `load` TINYINT UNSIGNED COMMENT 'Session loading value',
  `ipv4` INTEGER UNSIGNED COMMENT 'Session remote ipv4 or ipv6 signature',
  `name` CHAR( 64 ) COMMENT 'Session name',
)
COMMENT='Sessions list' ROW_FORMAT=FIXED;

Для расчета значения осмысленности отдельного запроса выделим отдельную функцию «sess_rate» ( для краткости реализации будет использован PHP ):

// * $show = «TIME» - разница в секундах между текущим временем
// * и временем последнего запроса
// * $base = «NORM» - эталонная форма поведения в секундах
// * $soft = «SAFE» - уровень доверия к запросам клиента,
// * мягкость распределения значений результата

function sess_rate( $show, $base = 20, $soft = 4 )
{
  // * Ограничим входное значение одним часом.
  // * Будем считать, что если пользователь
  // * не отвечает больше часа, смысловая
  // * нагрузка запроса не изменится
  $show = min( max( $show, 0 ), flTIME_HOUR );

  // * Считаем смысловую нагрузку запроса
  // * и ограничиваем возможный результат диапазоном
  return min( max( (int)( -log( ( ( $show + 1 ) * 1 / ( $base + 1 ) ), 1.01 + ( 0.02 * $soft ) ) ), -128 ), 128 );
}

Следующая функция «sess_wait» вызывается наряду с отправкой сервером ответа клиенту и сохранением информации в хранилище сессий:

function sess_wait( )
{
  // * Текущее время
  $time = microtime( );
  // * Признак AJAX запроса. Такие запросы подразумевают возможность
  // * быстрой реакции клиента, параметр «AUTO»
  $ajax = is_ajax_request( );

  // * Параметр «TIME» - разница в секундах между текущим временем
  // * и временем последнего запроса
  $show = ( $time - $sess['time'] );
  // * «NORM» - эталонная форма поведения в секундах
  $norm = $ajax ? 10 : 20;
  // * «SAFE» - уровень доверия к запросам клиента
  $soft = ( $sess['user'] > 0 ) ? 6 : 4;
  // * «RATE» - знаковое значение наличия смысловой нагрузки ( range: -128..128 )
  $rate = sess_rate( $show, $norm, $soft );
  // * Смысловая нагрузка сессии ( range: 0..255 )
  $load = max( 0, min( ( $sess['load'] + $rate ), 255 ) );

  // * Далее записываем значение $load в сессию и
  // * сохраняем ее в базу данных
}

Итог


В заключении приведу в качестве примера работы возвращаемые значения ( или фактор смысловой нагрузки запроса «RATE» ) для «TIME» от 0 до 59 секунд, при «NORM» = 20 секунд:

0 = 35; 1 = 27; 2 = 22; 3 = 19; 4 = 16; 5 = 14; 6 = 12;
7 = 11; 8 = 9; 9 = 8; 10 = 7; 11 = 6; 12 = 5; 13 = 4;
14 = 3; 15 = 3; 16 = 2; 17 = 1; 18 = 1; 19 = 0; 20 = 0;
21 = 0; 22 = -1; 23 = -1; 24 = -2; 25 = -2; 26 = -2; 27 = -3;
28 = -3; 29 = -4; 30 = -4; 31 = -4; 32 = -5; 33 = -5; 34 = -5;
35 = -6; 36 = -6; 37 = -6; 38 = -7; 39 = -7; 40 = -7; 41 = -8;
42 = -8; 43 = -8; 44 = -8; 45 = -9; 46 = -9; 47 = -9; 48 = -9;
49 = -10; 50 = -10; 51 = -10; 52 = -10; 53 = -10; 54 = -11; 55 = -11;
56 = -11; 57 = -11; 58 = -11; 59 = -12; 60 = -12;

Комментарии (0)