Еще немного про сессии MODX, компонент smartSessions
Всем привет!
Небольшая предыстория
Когда я на свой VPS сервер закинул очередной более-менее крупный сайт (в базе около 25 тыс. товаров), у меня начались проблемы с нехваткой памяти, mysql ее нещадно отъедал.
В процессе оптимизации я начал понимать, что у половины сайтов в базе большую часть объема занимает пресловутая таблица modx_sessions, где, как известно, лежат сессии посетителей.
Но… почему? У сайта посещаемость 150-200 человек в сутки, сессии хранятся 7 дней (да, я проверил, они действительно очищаются), но в таблице почему-то 200000 записей, хотя по логике вещей должно быть 200*7=1400+. Реальность расходится с теорией не на 5-10%, а в десятки раз!
В итоге таблица весит полгигабайта, сайтов штук 10, каждому дай памяти, вот VPS и падает периодически… непорядок!
Самый старый и известный материал на эту тему у нас здесь:
bezumkin.ru/sections/tips_and_tricks/2422/
Есть еще куча вопросов на этом сайте на предмет размера таблицы, да и вообще, все давно-давно терто-перетерто… вывод из всего — проверять, что сессии очищаются, уменьшать время хранения, но вот какая-то недосказанность все равно есть, что происходит понятно, а что с этим делать — не очень.
Нет, ну можно правда чистить таблицу с сессиями почаще, раз в 3 дня к примеру (настройка session_gc_maxlifetime), будет в целом терпимо. Но что делать, если я хочу, чтобы мой интернет-магазин хранил сессии месяц? Вот не хочу я пользователей заставлять постоянно вводить логин/пароль (или код из смс)!
И тут я наткнулся на статью lectoria.pro/read/sessii-v-php-i-modx-revolution.html и затем видео www.youtube.com/watch?v=GyzkQu_-vSI
Ба! Да все придумано уже, только вот реализации не нашел, готовый пакет почему-то так и не собран.
[smartSessions]
В общем собрал все в пакет, назвал smartSessions, вот иходники github.com/createit-ru/smartSessions
В чем суть работы:
— для сессий создана новая таблица modx_smart_sessions, которая повторяет родную modx_sessions, но добавлены колонки user_agent, ip, user_id
— написан свой обработчик сессий smartSessionHandler, который унаследован от родного modSessionHandler
Что сейчас может:
— можно отдельно установить время жизни сессий (настройка smartsessions_authorized_users_gc_maxlifetime ) для авторизованных пользователей.
— можно отдельно установить время жизни сессий (настройка smartsessions_bots_gc_maxlifetime) для различных ботов.
— в настройке smartsessions_bot_signatures можно указать перечень сигнатур этих самых ботов (будет произведен поиск LIKE по полю user_agent, например Googlebot|YandexBot|DotBot|bingbot|Mail.RU_Bot|PetalBot|MegaIndex.ru).
Как попробовать
— установите пакет из репозитория modstore;
— укажите в настройке session_handler_class значение smartSessionHandler;
— проверьте, что данные начали собираться в таблицу modx_smart_sessions. При этом таблицу modx_sessions можно очистить (не удалить, а очистить :)), она больше не нужна.
Благодаря расширенной таблице сессий я смог узнать кое-что новое о записях сессий.
Оказывается, что больше 95% записей в ней — это сессии различных ботов, и причем далеко не всегда это привычные Яндекс и Гугл, есть еще десятки других ботов, которые активно ходят по нашим сайтам.
Ситуация, когда в таблице 10000 записей сессий ботов и 200 записей реальных посетителей — обычная!
Например на своем сайте я настроил хранение сессий авторизованных пользователей 30 дней, неавторизованных 7 дней, а сессий ботов — 3 часа.
Результат — количество записей в таблице сессий снизилось в разы, нагрузка на mysql упала.
В качестве примера, выгрузка сессий, сгруппированных и отсортированных по user_agent за несколько часов.
Выделил сессии ботов, как видно их подавляющее большинство:
Дополнение доступно в ModStore:
modstore.pro/packages/utilities/smartsessions
Небольшая предыстория
Когда я на свой VPS сервер закинул очередной более-менее крупный сайт (в базе около 25 тыс. товаров), у меня начались проблемы с нехваткой памяти, mysql ее нещадно отъедал.
В процессе оптимизации я начал понимать, что у половины сайтов в базе большую часть объема занимает пресловутая таблица modx_sessions, где, как известно, лежат сессии посетителей.
Но… почему? У сайта посещаемость 150-200 человек в сутки, сессии хранятся 7 дней (да, я проверил, они действительно очищаются), но в таблице почему-то 200000 записей, хотя по логике вещей должно быть 200*7=1400+. Реальность расходится с теорией не на 5-10%, а в десятки раз!
В итоге таблица весит полгигабайта, сайтов штук 10, каждому дай памяти, вот VPS и падает периодически… непорядок!
Самый старый и известный материал на эту тему у нас здесь:
bezumkin.ru/sections/tips_and_tricks/2422/
Есть еще куча вопросов на этом сайте на предмет размера таблицы, да и вообще, все давно-давно терто-перетерто… вывод из всего — проверять, что сессии очищаются, уменьшать время хранения, но вот какая-то недосказанность все равно есть, что происходит понятно, а что с этим делать — не очень.
Нет, ну можно правда чистить таблицу с сессиями почаще, раз в 3 дня к примеру (настройка session_gc_maxlifetime), будет в целом терпимо. Но что делать, если я хочу, чтобы мой интернет-магазин хранил сессии месяц? Вот не хочу я пользователей заставлять постоянно вводить логин/пароль (или код из смс)!
И тут я наткнулся на статью lectoria.pro/read/sessii-v-php-i-modx-revolution.html и затем видео www.youtube.com/watch?v=GyzkQu_-vSI
Ба! Да все придумано уже, только вот реализации не нашел, готовый пакет почему-то так и не собран.
[smartSessions]
В общем собрал все в пакет, назвал smartSessions, вот иходники github.com/createit-ru/smartSessions
В чем суть работы:
— для сессий создана новая таблица modx_smart_sessions, которая повторяет родную modx_sessions, но добавлены колонки user_agent, ip, user_id
— написан свой обработчик сессий smartSessionHandler, который унаследован от родного modSessionHandler
Что сейчас может:
— можно отдельно установить время жизни сессий (настройка smartsessions_authorized_users_gc_maxlifetime ) для авторизованных пользователей.
— можно отдельно установить время жизни сессий (настройка smartsessions_bots_gc_maxlifetime) для различных ботов.
— в настройке smartsessions_bot_signatures можно указать перечень сигнатур этих самых ботов (будет произведен поиск LIKE по полю user_agent, например Googlebot|YandexBot|DotBot|bingbot|Mail.RU_Bot|PetalBot|MegaIndex.ru).
Как попробовать
— установите пакет из репозитория modstore;
— укажите в настройке session_handler_class значение smartSessionHandler;
— проверьте, что данные начали собираться в таблицу modx_smart_sessions. При этом таблицу modx_sessions можно очистить (не удалить, а очистить :)), она больше не нужна.
Благодаря расширенной таблице сессий я смог узнать кое-что новое о записях сессий.
Оказывается, что больше 95% записей в ней — это сессии различных ботов, и причем далеко не всегда это привычные Яндекс и Гугл, есть еще десятки других ботов, которые активно ходят по нашим сайтам.
Ситуация, когда в таблице 10000 записей сессий ботов и 200 записей реальных посетителей — обычная!
Например на своем сайте я настроил хранение сессий авторизованных пользователей 30 дней, неавторизованных 7 дней, а сессий ботов — 3 часа.
Результат — количество записей в таблице сессий снизилось в разы, нагрузка на mysql упала.
В качестве примера, выгрузка сессий, сгруппированных и отсортированных по user_agent за несколько часов.
SELECT `user_agent`, COUNT(*)
FROM `modx_smart_sessions`
GROUP BY `user_agent`
ORDER BY `COUNT(*)` DESC
Выделил сессии ботов, как видно их подавляющее большинство:
Дополнение доступно в ModStore:
modstore.pro/packages/utilities/smartsessions
Комментарии: 73
Спасибо Алексей!
или, может, я его когда-то опубликую, если будет интересинтерес есть, было бы классно ;-)
Плюсую, интерес есть определенно
Ох уж эти сессии. Да, в modx хранение сессий в базе приводит к тому, что таблица с сессиями занимает огромное место. У меня есть посещаемый сайт и там только таблица с сессиями занимает 17 гигабайт.
Сейчас работаю над закрытым порталом для сотрудников одной крупной мировой компанией и тоже пришлось глубоко погрузится в мир сессий.
К моему счастью, раз в сутки в 3 часа ночи происходит полное обновление данных о сотрудниках и я могу просто запустить скрипт по удалению файлов сессии. Это позволяет разлогинить всех сотрудников, чтобы утром каждый вошел (если не уволен за ночь) с новыми правами и плюс, не заводить кучу файлов сессий. Раз в сутки все файлы просто удаляются.
Сейчас работаю над закрытым порталом для сотрудников одной крупной мировой компанией и тоже пришлось глубоко погрузится в мир сессий.
К моему счастью, раз в сутки в 3 часа ночи происходит полное обновление данных о сотрудниках и я могу просто запустить скрипт по удалению файлов сессии. Это позволяет разлогинить всех сотрудников, чтобы утром каждый вошел (если не уволен за ночь) с новыми правами и плюс, не заводить кучу файлов сессий. Раз в сутки все файлы просто удаляются.
Есть же возможность хранить сессии в файлах? Или это не правильно?
Ещё правильнее хранить сессии в Redis.
При правильных настройках — у активных пользователей сессия не будет слетать (так как часто запрашивается).
А менее популярные сессии анонимов при большом размере кеша будут выталкиваться.
Так и при установке MODX на два сервера и более репликация Redis позволит не слетать авторизациям между запросами на разные сервера (именно тут у сессий в БД и было преимущество над файлами, где тоже можно было настроить репликацию БД между серверами).
Но я не знаю и не делал сайтов на MODX, работающих одновременно на двух серверах)
При правильных настройках — у активных пользователей сессия не будет слетать (так как часто запрашивается).
А менее популярные сессии анонимов при большом размере кеша будут выталкиваться.
Так и при установке MODX на два сервера и более репликация Redis позволит не слетать авторизациям между запросами на разные сервера (именно тут у сессий в БД и было преимущество над файлами, где тоже можно было настроить репликацию БД между серверами).
Но я не знаю и не делал сайтов на MODX, работающих одновременно на двух серверах)
Ещё правильнее хранить сессии в Redis.Ну тут Евгений, наверное стоит заметить, что сайты разрабатываемые на modx как правило размещаются на очень недорогих хостингаx, где нет возможности установить redis. Как это по русски — каждый сверчок знай свой шесток.
При правильных настройках — у активных пользователей сессия не будет слетать (так как часто запрашивается).У вас нет ссылок на примеры реализации? Просто я буквально неделю назад углубленно вникал в работу redis и скажем так — не нашел redis очень удобным для хранения сессий. Применил redis для хранения временных токенов, для доступа у определенным ресурсам — вот тут прям идеально применение redis поскольку программа имеет возможность установки времени жизни записи и сама следит за ее удалением.
А менее популярные сессии анонимов при большом размере кеша будут выталкиваться.
Так и при установке MODX на два сервера и болеенеужели кто-то так делает? MODX это возможность за 6 дней сделать неплохо работающий сайт, лендинг, небольшой магазин без амбиций. Но распылять MODX на несколько серверов… Мне кажется это из области фантастики. Здесь на форуме собраны лучшие разработчики на MODX в России и бывших странах СССР — кто так делал?
У вас нет ссылок на примеры реализации?Я делал. Для начала нужно установить на сервер github.com/phpredis/phpredis
В MODX нужно всего лишь очистить системную настройку session_handler_class — в этом случае за сессии будет отвечать PHP и по умолчанию будет хранить их в файлах.
Для хранения их в redis нужно в php.ini указать:
session.save_handler = redis
session.save_path = "tcp://host1:6379?weight=1, tcp://host2:6379?weight=2&timeout=2.5, tcp://host3:6379?weight=2&read_timeout=2.5"
; а для тех кто, как и я предпочитает подключение по сокету в пределах одной машины:
session.save_path = "unix:///var/run/redis/redis.sock?persistent=1&weight=1&database=0"
; но в этом случае нужно ещё в redis.conf указать этот же путь в unixcocket
И теперь уже PHP будет отвечать за хранение сессий в redis.
Более подробнее уже несложно нагуглить)
Да спасибо Евгений, примерно по такому пути и я смотрел.
Правда не стал использовать phpredis а взял вот эту программу cheprasov/php-redis-client
Но дело ведь в том, что редис сам по себе не гарантирует сохранность данных.
Если мы храним сессии в файлах, то они там и остаются. Храним сессии в базе — они там и остаются. А редис это все таки хранилище которое живет в оперативной памяти и при выключении питания на сервере к примеру — все будет потеряно. Да редис умеет периодически сбрасывать данные на жесткий диск, но все это не гарантируется разработчиком.
Правда не стал использовать phpredis а взял вот эту программу cheprasov/php-redis-client
Но дело ведь в том, что редис сам по себе не гарантирует сохранность данных.
Если мы храним сессии в файлах, то они там и остаются. Храним сессии в базе — они там и остаются. А редис это все таки хранилище которое живет в оперативной памяти и при выключении питания на сервере к примеру — все будет потеряно. Да редис умеет периодически сбрасывать данные на жесткий диск, но все это не гарантируется разработчиком.
Если мы храним сессии в файлах, то они там и остаются. Храним сессии в базе — они там и остаются.А если жёсткий диск полетит?)
все будет потеряноА в сессии ничего важного и не должно быть. Максимальные потери здесь — содержимое корзины да и выход из аккаунта. А если настроить сохранение на диск, то и потеряется только сессионные данные за последние n секунд)
У Redis есть режим персистентности, так что данные не будут потеряны. У нас в огромном проекте (не MODX) редис активно используется именно для сессий, потому что по другому не получается. К тому же кластер редиса хорошо масштабируется и позволяет запускать по 10 и более инстансов приложения, при этом пользователь не теряет своей сессии, даже если балансировщик подсунул ему другую машину.
Уверен вы правы. Просто я еще не дорос до проектов, у которых есть балансировщики нагрузки и сопутствующие им проблемы.
Вопрос не в дорос или нет, просто увидел в посте заблуждение, которое стало личным убеждением, и постарался его развеять.
я имел ввиду, что выбор инструмента для решения задачи исходит из самой задачи. Возможно для таких систем как ваша, где запрос пользователя случайным образом отправляется на разные сервера, то выбор redis является правильным и удобным инструментом. Хотя не совсем понимаю, как это устроено. Редис работает одновременно на всех серверах и везде данные синхронизированы?
редис работает как единый сервис в amazon, а уже отдельные серверы с приложением к нему подключаются. Т.е. там одна общая база для всех.
Выступлю в роли Николая Ланца… Идея отличная!!! Но к реализации очень много вопросов.
Писать в базу нефильтрованный USER_AGENT — это чтобы пощекотать себе нервы?
Ну и про наследование в ООП советовал бы почитать.
Режим «Николай Ланец» OFF. ))
— для сессий создана новая таблица modx_smart_sessions, которая повторяет родную modx_sessionsЗачем? Теперь лишняя таблица в базе болтается. Для таких целей используют миграции. В MODX их нет, но можно расширить схему.
Писать в базу нефильтрованный USER_AGENT — это чтобы пощекотать себе нервы?
Ну и про наследование в ООП советовал бы почитать.
Режим «Николай Ланец» OFF. ))
Так у меня и только beta версия только выпущена)))
Но за здравую критику — спасибо
Но за здравую критику — спасибо
Вообще хорошо бы понимать, что сессии должны создаваться только для авторизованных пользователей. Вряд ли все эти посетители, которые заходят на ваш сайт, регистрируются и авторизуются. Более разумно просто отказаться от использования таких дополнений как AjaxForm, который для каждого посетителя создает сессию. Тогда таблица вообще не будет пухнуть.
Дополнение. Прочитал по ссылке и ужаснулся:
При посещении какой-либо веб-страницы сайта, созданного на PHP, создается сессия.Видимо автор этого текста изучает PHP только в совокупности с MODX (и AjaxForm).
В сессии хранятся данные, которые присущи только вашему визиту. Например, корзина товаров, информация о том, авторизовались ли вы для входа в личный кабинет и так далее.А если я не авторизовался и ничего не положил в корзину, то и сессия мне не нужна. На нормальных сайтах именно так и происходит.
Что значит только для авторизованных?..
А корзина товаров? А если я товар «отложил», а если я перешел по реферальной ссылке на сайт, а если у нас правда что-то работает через ajax?
Правильнее бы конечно создавать сессии когда они действительно нужны. Но MODX работает на своей волне, а кажется именно его мы здесь и обсуждаем.
Давайте делать статичные странички на html!
А корзина товаров? А если я товар «отложил», а если я перешел по реферальной ссылке на сайт, а если у нас правда что-то работает через ajax?
Правильнее бы конечно создавать сессии когда они действительно нужны. Но MODX работает на своей волне, а кажется именно его мы здесь и обсуждаем.
Более разумно просто отказаться от использования таких дополнений как AjaxForm, который для каждого посетителя создает сессию.
Давайте делать статичные странички на html!
А корзина товаров? А если я товар «отложил»...Про это я уже написал. Зачем повторяться? Какой процент всех посетителей использует корзину товаров? Я думаю меньше 50%.
а если у нас правда что-то работает через ajax?Для аякса необходимы сессии? Это что-то новенькое)
Правильнее бы конечно создавать сессии когда они действительно нужны. Но MODX работает на своей волнеНе MODX, а указанное дополнение.
Давайте делать статичные странички на html!Ну да, переписать дополнение или использовать другое не нужно. А нужно к этому дополнению городить кучу костылей))
Уточню что я имею ввиду. Да, в MODX есть особенность, что если отключить «anonymous_sessions», то сессии будут работать только у авторизованных пользователей. В некоторых случаях это подходит (заставлять авторизовываться). Но важен также размер хранящейся информации в таблице сессии. Его нужно свести к минимуму + уменьшить время жизни сессии до суток (или даже 12 часов). Этого вполне достаточно для большинства сайтов. Но по-хорошему эту особенность с «anonymous_sessions» нужно исправить. Сессии должны создаваться только тогда, когда они нужны.
Так вот компонент и решает задачу:
1. отдельно управлять временем жизни сессий для авторизованных пользователей (например, поставить им месяц);
2. отдельно управлять временем жизни сессий ботов (к примеру, поставить им 3 часа);
3. У всех остальных — ну пусть будет стандартная неделя.
И на моих сайтах, за счет п.2. размер таблицы и объем данных уменьшился в десятки раз, т.к. именно сессии различных ботов составляли 90% записей в таблице.
1. отдельно управлять временем жизни сессий для авторизованных пользователей (например, поставить им месяц);
2. отдельно управлять временем жизни сессий ботов (к примеру, поставить им 3 часа);
3. У всех остальных — ну пусть будет стандартная неделя.
И на моих сайтах, за счет п.2. размер таблицы и объем данных уменьшился в десятки раз, т.к. именно сессии различных ботов составляли 90% записей в таблице.
Ну да, переписать дополнение или использовать другое не нужно. А нужно к этому дополнению городить кучу костылей))@Иван хоть вы на первый взгляд и детально объяснили что там как должно быть на нормальных по вашему мнению сайтах, все же не понятно какую проблему вы видите в дополнении? Какие необходимые к нему костыли вы имеете в виду?
Во времена повсеместного бума интернет-приватности и частичного отказа от cookies я вот хочу перенести в сессии некоторые настройки персонализации для незарегистрированных посетителей сайта (например открыто или закрыто боковое меню) и вообще сводить к минимуму использование cookies там где возможно.
Короче, ИМХО тренд сейчас в сторону увеличения времени жизни сессий, а не уменьшению.
Поэтому, если не «плакаться» что «anonymous_sessions» работает не так как хочется, а так, как решил мейнтейнер (хотя может и открыть ещё один issue для обсуждения?), то проблему с растущей базой надо как-то решать всё равно, а идея проверять user-agent и через него фильтровать сессии ботов это же прям похоже на решение!
Я писал про дополнение «AjaxForm» (может ещё какое-то есть), которое очень популярно. Этот сниппет для каждого посетителя сайта (в т.ч. для ботов) создает записи в сессии, где хранит параметры сниппетов. Представляете какой это объём информации для сайта с хорошей посещаемостью? Сталкивался с сайтами, где на одну страницу минимум 5 раз используется AjaxForm.
Во времена повсеместного бума интернет-приватности и частичного отказа от cookies я вот хочу перенести в сессии некоторые настройки персонализации для незарегистрированных посетителей сайта (например открыто или закрыто боковое меню) и вообще сводить к минимуму использование cookies там где возможно.К Вашему сведению, сессия работает через куку, где хранится её ID. Так что переводить на сессию в Вашем случае смысла нет. Лучше используйте в JS LocalStorage или SessionStorage. Технологии нужно использовать по их назначению, тогда и проблем не будет.
Бывает же такое, как раз ищу инфу по уменьшению размер таблицы с сессиями (на одном проекте 3.2гб уже), нахожу массу вариантов из поиска, включая статью про сессии на bezumkin.ru (кстати она от 2014 г и спустя 7 лет, в ubuntu значение session.gc_probability и сейчас по-умолчанию = 0 ).
Ну подправил настройки PHP и довольный по привычке перехожу на главную modx.pro глянуть как дела и вижу тут большой новый пост про сессии (0_о)… уже заподозрил что рекламные-таргет-технологии добрались до портала и подкладывают рекомендации на основе истории поиска :)
Оказалось, совпадение…
P.S. Автору большое спасибо! Конечно, готовые решения намного лучше когда в пакетах!
Ну подправил настройки PHP и довольный по привычке перехожу на главную modx.pro глянуть как дела и вижу тут большой новый пост про сессии (0_о)… уже заподозрил что рекламные-таргет-технологии добрались до портала и подкладывают рекомендации на основе истории поиска :)
Оказалось, совпадение…
P.S. Автору большое спасибо! Конечно, готовые решения намного лучше когда в пакетах!
Потестил компонент, не работает функционал «Завершить все сеансы» — может быть имело смысл не создавать свою таблицу, а расширить существующую и тогда бы это работало. В итоге получаем ошибку —
А так затея интересная, автору респект.
А так затея интересная, автору респект.
Точно, будем фиксить в следующих версиях)
Просто не выйдет…
MODX не умеет очищать сессии, если используется иной, отличный от modSessionHandler класс.
В процессоре проверяется настройка session_handler_class, и если там указано что-то не стандартное — сразу ошибка.
Как вариант — сделать свой пункт в меню для очистки сессий, а стандартный скрыть… ну и тогда нужно дописать процессор и т.п.
MODX не умеет очищать сессии, если используется иной, отличный от modSessionHandler класс.
В процессоре проверяется настройка session_handler_class, и если там указано что-то не стандартное — сразу ошибка.
Как вариант — сделать свой пункт в меню для очистки сессий, а стандартный скрыть… ну и тогда нужно дописать процессор и т.п.
MODX не умеет очищать сессии, если используется иной, отличный от modSessionHandler класс.Вот это шляпа. По хорошему нужно править это.
Самый простой выход — через js в админке менять хандлер у этого пункта меню, в котором указать свой процессор (поправленную копию системного процессора).
А самый правильный — интерфейс ISessionHandler с методом flushSessions, от которого наследуется уже modSessionHandler, и что бы именно он вызывался в процессоре.
Правильный — да, реальный — нет. В двойку это не добавят, а тройка никогда не выйдет. Поэтому нужно рулить в рамках пакета.
П.С. К слову, я не сторонник С-ишных названий с префиксом I. Да и суффикс Interface, наверно, всё-таки лишний. По-современному должно быть так — интерфейс SessionHandler, а реализации — modSessionHandler, AntibotSessionHandler и т.п.
П.С. К слову, я не сторонник С-ишных названий с префиксом I. Да и суффикс Interface, наверно, всё-таки лишний. По-современному должно быть так — интерфейс SessionHandler, а реализации — modSessionHandler, AntibotSessionHandler и т.п.
А абстрактный класс тогда как назвать, если SessionHandler занято интерфейсом? BaseSessionHandler?
Я с C# много работал N лет назад, в голове все это еще прочно сидит)
Я с C# много работал N лет назад, в голове все это еще прочно сидит)
BaseSessionHandler?Подойдёт. Таким образом есть понимание, где интерфейс, а где реализация (при DI). Но как правило, одновременно интерфейсы и абстрактные классы используют редко. Для проекта достаточно абстрактного класса, для библиотеки — интерфейса. В общих случаях. Ну и пространства имён никто не отменял (для одинаковых названий).
Вам PSR о чем-нибудь говорит? www.php-fig.org/bylaws/psr-naming-conventions/ — первые 3 пункта.
Отличная идея для дополнения!
Но я тоже за расширение оригинальной таблицы modx_sessions через свой плагин для добавления колонок.
Но я тоже за расширение оригинальной таблицы modx_sessions через свой плагин для добавления колонок.
Госпаде! Спасибо Вам святой Вы человек! Пусть мана небесная сыплется бесконечно! Это реально ускоряет работу сайта, прям глаза открыли :DDD
П.С.
А еще закинул чуть чуть рублс для стимуляции подвигов, а это без сомнений подвиг!
П.С.
А еще закинул чуть чуть рублс для стимуляции подвигов, а это без сомнений подвиг!
Ого, спасибо)
заметил один баг, он не прям совсем неприятный, но когда добавляешь допустим пользователя в определенную группу, например был он в группе: Users, а нужно еще добавить добавить в Bussines, то раньше при чистке КЕШа и перезагрузке прав, помогало не перелогиниваться пользователю и сразу пользоваться преимуществами новой группы, а сейчас нужно в базе удалять сессию.
Я может конечно чет не так понял… но это случилось после того как перешел на этот обработчик! Не подскажите в чем может быть проблемс?
Я может конечно чет не так понял… но это случилось после того как перешел на этот обработчик! Не подскажите в чем может быть проблемс?
@Наумов Алексей приветствую. Классное дополнение, вы молодец.
Есть вот такая ошибка в логах:
Есть вот такая ошибка в логах:
[2024-02-19 14:43:00] (ERROR @ /www/core/xpdo/om/xpdoobject.class.php : 240) Error HY000 executing statement:
Array
(
[0] => HY000
[1] => 2014
[2] => Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
)
[2024-02-19 14:43:00] (ERROR @ /www/core/xpdo/om/xpdoobject.class.php : 1452) Error HY000 executing statement:
INSERT INTO `modx_smart_sessions` (`id`, `access`, `ip`, `user_agent`, `data`) VALUES ('8u218rm3v5d92au80cqe497mgt', 1708342980, 'support@search.yandex.ru', 'Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)', 'modx.user.contextTokens|a:0:{}modx.user.0.resourceGroups|a:1:{s:5:\"proza\";a:0:{}}modx.user.0.attributes|a:1:{s:5:\"proza\";a:5:{s:16:\"modAccessContext\";a:15:{s:6:\"author\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:4:\"beta\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:4:\"blog\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:5:\"event\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:8:\"gramotno\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:7:\"konkurs\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:8:\"litkursy\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:3:\"mag\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:5:\"proza\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:7:\"publish\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:6:\"rabota\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:5:\"stihi\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:6:\"theory\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:4:\"typo\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}s:3:\"web\";a:1:{i:0;a:3:{s:9:\"principal\";i:0;s:9:\"authority\";s:1:\"0\";s:6:\"policy\";a:3:{s:4:\"load\";b:1;s:6:\"formit\";b:1;s:18:\"formit_encryptions\";b:0;}}}}s:22:\"modAccessResourceGroup\";a:0:{}s:17:\"modAccessCategory\";a:0:{}s:28:\"sources.modAccessMediaSource\";a:0:{}s:18:\"modAccessNamespace\";a:0:{}}}Tickets_User|s:32:\"99c2d8d1749f889d870d70c625fecb6e\";')
Array
(
[0] => HY000
[1] => 2014
[2] => Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
)
[2024-02-19 14:43:00] (ERROR @ Unknown0) PHP warning: Unknown: Failed to write session data using user defined save handler. (session.save_path: /var/lib/php/sessions)
При этом в кончиках не указан этот путь "/var/lib/php/sessions" для сохранения сессий (строка закомментирована). В чём может быть дело?
Эта ошибка обычно означает попытку записать в сессию данные, в тот момент, когда не завершился еще прошлый запрос. То есть обращения к сессии через чур быстрые. Не успевает обработать. Сессии внутри баз данных немного медленнее работают, чем файловые сессии.
Похоже, придётся вернуться на файловые сессии.
А если перейти на modSessionHandler ошибки так же появляются?
Володя, спасибо за участие. Потестирую со стандартным.
Привет, ну да, верно написал Николай, ошибка из-за того, что один запрос еще не завершен, а система отправляет второй. Посещаемость большая? Ошибка частая или разок проскочила?
Я, когда руки дойдут до smartSessions, попробую оптимизировать компонент, может побыстрее будет работать.
Я, когда руки дойдут до smartSessions, попробую оптимизировать компонент, может побыстрее будет работать.
Алексей, здравствуйте.
Ошибки появляются несколько раз в день. Посещаемость +\- 10к в сутки. Но бывает больше. Иногда растёт скачкообразно. Видимо, в такие моменты и случается ошибка.
Видел похожий компонент от Володи. Для MODx3. modx.pro/components/24542. Там в комментах тоже были вопросы по оптимизации. Может быть поможет.
Спасибо за отзывчивость, Алексей. Будем ждать обновления.
Ошибки появляются несколько раз в день. Посещаемость +\- 10к в сутки. Но бывает больше. Иногда растёт скачкообразно. Видимо, в такие моменты и случается ошибка.
Видел похожий компонент от Володи. Для MODx3. modx.pro/components/24542. Там в комментах тоже были вопросы по оптимизации. Может быть поможет.
Спасибо за отзывчивость, Алексей. Будем ждать обновления.
Как я понимаю, таблица начинает расти в прогрессии, если есть много контекстов. Так как данные пишет для каждого контекста, дублируя их. Интересно, это можно как-то оптимизировать?
И ещё вопрос: как дополнение понимает когда чистить таблицу — нет поля для хранения даты создания сессии. Или я как-то неправильно понял механизм работы?
Поле access есть: см. исходники.
… таблица начинает расти в прогрессии, если есть много контекстовВ этом дополнении нет ничего нового, связанного с контекстами, по сравнению со стандартным sessionhandler. Основная цель дополнения — расширить таблицу сессий, чтобы в ней хранился user-agent. И если user-agent принадлежит боту — чистить такие сессии раньше, не хранить их долго.
И нужно исключить возможность вот такой ошибки :)Эта ошибка возникла из-за того, что оказался поврежден файл с таблицей БД. Причина, по которой произошла данная ситуация, вероятно, связана с каким-то сбоем на сервере. К примеру, у меня раньше часто из-за нехватки памяти падал процесс mysql, и эти падения иногда заканчивались повреждением отдельных таблиц БД, весьма часто таблицы с сессией (потому что эта таблица каждый раз при открытии любой страницы сайта обновляется), но иногда и таблиц вроде site_content. Увеличение объема памяти решило в моем случае проблему с падающим mysql и повреждением таблиц.
Я вообще зачем дополнение сделал:
У моего сайта была посещаемость 300 человек в сутки. В неделю это 7*300=2100 человек. Сессии как раз неделю и хранились. Вот только в таблице сессий было не 2000 записей, как было бы ожидаемо, а около 100-200 тысяч. Когда я начал изучать вопрос — боты, одни боты! яндекс, гугл, просто wget какие-то, индексаторы картинок, парсеры… чего только не было) и что забавное — почти всегда каждый запрос генерил новую сессию, боты не держали её)) а итоге приходит яндекс бот на сайт, индексирует сайт, 3000 страниц — о-ппа и +3000 сессий. А кому они нужны?)
У моего сайта была посещаемость 300 человек в сутки. В неделю это 7*300=2100 человек. Сессии как раз неделю и хранились. Вот только в таблице сессий было не 2000 записей, как было бы ожидаемо, а около 100-200 тысяч. Когда я начал изучать вопрос — боты, одни боты! яндекс, гугл, просто wget какие-то, индексаторы картинок, парсеры… чего только не было) и что забавное — почти всегда каждый запрос генерил новую сессию, боты не держали её)) а итоге приходит яндекс бот на сайт, индексирует сайт, 3000 страниц — о-ппа и +3000 сессий. А кому они нужны?)
Да, полностью согласен с этим. Компонент нужный. Вы молодец :))
Алексей, а что делать, если таблица не очищается от сессий ботов? Хотя для ботов стоит время 10800.
Ну а сигнатуры то ботов нужных прописаны в настройках (smartsessions_bot_signatures)?
Это довольно индивидуальный параметр для каждого сайта. Если не очищается совсем — то gc не работает в php, с ним нужно копать, вот чтиво десятилетней давности: bezumkin.ru/sections/tips_and_tricks/2422
Это довольно индивидуальный параметр для каждого сайта. Если не очищается совсем — то gc не работает в php, с ним нужно копать, вот чтиво десятилетней давности: bezumkin.ru/sections/tips_and_tricks/2422
Благодарю за ответ. У вас эти настройки PHP (gc) как выставлены?
честно говоря не помню, там и есть то пара их: что вообще включено, и делитель, у меня наверное 1/100 стоит
Да, так же выставил.
Сигнатуры прописаны.
И выдает вот такие ошибки:
[2024-02-26 19:43:34] (ERROR in xPDOConnection::connect @ /www/core/xpdo/xpdo.class.php : 3125) SQLSTATE[HY000] [2002] No such file or directory
[2024-02-26 19:43:34] (ERROR @ /www/core/xpdo/om/xpdoobject.class.php : 263) Error preparing statement for query: SELECT `smartSession`.`id` AS `smartSession_id`, `smartSession`.`access` AS `smartSession_access`, `smartSession`.`ip` AS `smartSession_ip`, `smartSession`.`user_id` AS `smartSession_user_id`, `smartSession`.`user_agent` AS `smartSession_user_agent`, `smartSession`.`data` AS `smartSession_data` FROM `modx_smart_sessions` AS `smartSession` WHERE `smartSession`.`id` = ? -
[2024-02-26 19:43:34] (ERROR in xPDOConnection::connect @ /www/core/xpdo/xpdo.class.php : 3125) SQLSTATE[HY000] [2002] No such file or directory
[2024-02-26 19:43:34] (ERROR in xPDOConnection::connect @ /www/core/xpdo/xpdo.class.php : 3125) SQLSTATE[HY000] [2002] No such file or directory
[2024-02-26 19:43:34] (ERROR @ Unknown0) PHP warning: Unknown: Failed to write session data using user defined save handler. (session.save_path: /var/lib/php/sessions)
И такие ошибки:
[2024-02-26 20:25:30] (ERROR @ /www/core/xpdo/xpdo.class.php : 988) xPDO->removeCollection - Error deleting smartSession instances using query DELETE FROM `modx_smart_sessions` WHERE ( `modx_smart_sessions`.`access` < '1708957438' AND `modx_smart_sessions`.`user_agent` LIKE '%YandexMarket%' )
[2024-02-26 20:25:42] (ERROR @ /www/core/xpdo/xpdo.class.php : 988) xPDO->removeCollection - Error deleting smartSession instances using query DELETE FROM `modx_smart_sessions` WHERE ( `modx_smart_sessions`.`access` < '1708957460' AND `modx_smart_sessions`.`user_agent` LIKE '%YandexTurbo%' )
[2024-02-26 20:25:53] (ERROR @ /www/core/xpdo/xpdo.class.php : 988) xPDO->removeCollection - Error deleting smartSession instances using query DELETE FROM `modx_smart_sessions` WHERE ( `modx_smart_sessions`.`access` < '1708957502' AND `modx_smart_sessions`.`user_agent` LIKE '%YandexBot%' )
[2024-02-26 20:25:56] (ERROR @ /www/core/xpdo/xpdo.class.php : 988) xPDO->removeCollection - Error deleting smartSession instances using query DELETE FROM `modx_smart_sessions` WHERE ( `modx_smart_sessions`.`access` < '1708957420' AND `modx_smart_sessions`.`user_agent` LIKE '%DataForSeoBot%' )
странные ошибки
база то в порядке? таблица жива?
база то в порядке? таблица жива?
Да, таблицу чистил вручную по вхождениям сигнатур ботов)
Попробовал поискать ошибку. Яндекс показал это:
forums.modx.com/thread/103530/howto-remove-collection-from-custom-table
forums.modx.com/thread/103530/howto-remove-collection-from-custom-table
Теперь после удаления сайт падает наглухо :)
С такими ошибками в логах NGINX:
Помогает только копирование файлов из бэкапа. В чем может быть дело?
С такими ошибками в логах NGINX:
2024/02/28 04:07:05 [error] 545#545: *31 FastCGI sent in stderr: "PHP message: PHP Warning: include(/www/core/components/smartsessions/model/smartsessionhandler.class.php): failed to open stream: No such file or directory in /www/core/model/modx/smartsessionhandler.class.php on line 6PHP message: PHP Warning: include(): Failed opening '/www/core/components/smartsessions/model/smartsessionhandler.class.php' for inclusion (include_path='.:/usr/share/php') in /www/core/model/modx/smartsessionhandler.class.php on line 6PHP message: PHP Fatal error: Uncaught Error: Class 'smartSessionHandler' not found in /www/core/model/modx/modx.class.php:2578
Настройку session_handler_class меняю на modSessionHandlerПомогает только копирование файлов из бэкапа. В чем может быть дело?
Сначала нужно вернуть настройку session_handler_class на modSessionHandler, и только потом удалять компонент, так должно быть все нормально
По хорошему этот пункт должен быть в качестве резолвера в компоненте.
Да, выпустил обновку. TODO в коде оказывается с самого начала на этот момент висел.
Алексей, а с предыдущими ошибками о которых писал удалось разобраться?
Ну они плавающие, я не знаю, в чем причины. Я провел некоторую оптимизацию компонента, может что-то и исправилось
Перенос из modx.pro/components/24542#comment-142930
Проанализировал код
1. Во время удаления сессий выполняется N запросов, если быть точным то сколько прописано сигнатур user agent столь и будет выполнено запросов
2. Поле user_agent не индексное, то есть это будут медленные запросы
Еще хотел узнать, зачем для ботов создавать сессию?
И потом её удалять, целесообразность этого функционал не понимаю
особенно с учетом тяжести запросов в цикле
Перенесу и свой ответ тогда уж!:
пару месяцев назад я переписал это всё… сейчас по другому, в github код доступен. Можно даже PR сделать!Интересная мысль насчет целесообразности создания сессий для ботов… в принципе может они и не нужны… как вариант можно добавить соответствующую настройку в компонент. В общем мысль сохранил.
Вам бы, коллеги, скооперироваться чтобы список ботов (user agent-ов) общий использовать для botAim и SmartSessions)
Предлагаю, если нужно, захостить его там же, где статистика установки компонентов, в надёжной инфраструктуре одного из крупных ДЦ. Я поспособствую!
Или выпустить список в качестве отдельного пакета, который наследовать, чтобы обновлять средствами MODX.
С каждым годом всё больше и больше проблем от ботов. Ваши решения (Алексея и Андрея) очень помогают, и необходимость в них только растёт!
Предлагаю, если нужно, захостить его там же, где статистика установки компонентов, в надёжной инфраструктуре одного из крупных ДЦ. Я поспособствую!
Или выпустить список в качестве отдельного пакета, который наследовать, чтобы обновлять средствами MODX.
С каждым годом всё больше и больше проблем от ботов. Ваши решения (Алексея и Андрея) очень помогают, и необходимость в них только растёт!
[2024-05-13 11:18:51] (ERROR @ Unknown0) PHP warning: Unknown: Cannot call session save handler in a recursive manner
Запись в базу работает, но в журнале эта запись. Кто-то уже сталкивался с этим нюансом?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.