Еще немного про сессии 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 за несколько часов.
SELECT `user_agent`, COUNT(*) 
FROM `modx_smart_sessions` 
GROUP BY `user_agent` 
ORDER BY `COUNT(*)` DESC

Выделил сессии ботов, как видно их подавляющее большинство:


Дополнение доступно в ModStore:
modstore.pro/packages/utilities/smartsessions
Наумов Алексей
28 июля 2021, 10:51
modx.pro
15
5 043
+29

Комментарии: 73

Sergey (Sentinel)
28 июля 2021, 10:59
+2
Спасибо Алексей!

или, может, я его когда-то опубликую, если будет интерес
интерес есть, было бы классно ;-)
Александр Мельник
28 июля 2021, 19:27
0
Ох уж эти сессии. Да, в modx хранение сессий в базе приводит к тому, что таблица с сессиями занимает огромное место. У меня есть посещаемый сайт и там только таблица с сессиями занимает 17 гигабайт.
Сейчас работаю над закрытым порталом для сотрудников одной крупной мировой компанией и тоже пришлось глубоко погрузится в мир сессий.
К моему счастью, раз в сутки в 3 часа ночи происходит полное обновление данных о сотрудниках и я могу просто запустить скрипт по удалению файлов сессии. Это позволяет разлогинить всех сотрудников, чтобы утром каждый вошел (если не уволен за ночь) с новыми правами и плюс, не заводить кучу файлов сессий. Раз в сутки все файлы просто удаляются.
    Роман
    29 июля 2021, 17:18
    +1
    Есть же возможность хранить сессии в файлах? Или это не правильно?
      Евгений Шеронов
      01 августа 2021, 13:00
      0
      Ещё правильнее хранить сессии в Redis.
      При правильных настройках — у активных пользователей сессия не будет слетать (так как часто запрашивается).
      А менее популярные сессии анонимов при большом размере кеша будут выталкиваться.

      Так и при установке MODX на два сервера и более репликация Redis позволит не слетать авторизациям между запросами на разные сервера (именно тут у сессий в БД и было преимущество над файлами, где тоже можно было настроить репликацию БД между серверами).

      Но я не знаю и не делал сайтов на MODX, работающих одновременно на двух серверах)
        Александр Мельник
        01 августа 2021, 14:14
        0
        Ещё правильнее хранить сессии в Redis.
        Ну тут Евгений, наверное стоит заметить, что сайты разрабатываемые на modx как правило размещаются на очень недорогих хостингаx, где нет возможности установить redis. Как это по русски — каждый сверчок знай свой шесток.
        При правильных настройках — у активных пользователей сессия не будет слетать (так как часто запрашивается).
        А менее популярные сессии анонимов при большом размере кеша будут выталкиваться.
        У вас нет ссылок на примеры реализации? Просто я буквально неделю назад углубленно вникал в работу redis и скажем так — не нашел redis очень удобным для хранения сессий. Применил redis для хранения временных токенов, для доступа у определенным ресурсам — вот тут прям идеально применение redis поскольку программа имеет возможность установки времени жизни записи и сама следит за ее удалением.
        Так и при установке MODX на два сервера и более
        неужели кто-то так делает? MODX это возможность за 6 дней сделать неплохо работающий сайт, лендинг, небольшой магазин без амбиций. Но распылять MODX на несколько серверов… Мне кажется это из области фантастики. Здесь на форуме собраны лучшие разработчики на MODX в России и бывших странах СССР — кто так делал?
          Евгений Шеронов
          02 августа 2021, 14:51
          1
          +2
          У вас нет ссылок на примеры реализации?
          Я делал. Для начала нужно установить на сервер 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.
          Более подробнее уже несложно нагуглить)
            Александр Мельник
            02 августа 2021, 16:30
            0
            Да спасибо Евгений, примерно по такому пути и я смотрел.
            Правда не стал использовать phpredis а взял вот эту программу cheprasov/php-redis-client
            Но дело ведь в том, что редис сам по себе не гарантирует сохранность данных.
            Если мы храним сессии в файлах, то они там и остаются. Храним сессии в базе — они там и остаются. А редис это все таки хранилище которое живет в оперативной памяти и при выключении питания на сервере к примеру — все будет потеряно. Да редис умеет периодически сбрасывать данные на жесткий диск, но все это не гарантируется разработчиком.
              Евгений Шеронов
              03 августа 2021, 19:35
              +1
              Если мы храним сессии в файлах, то они там и остаются. Храним сессии в базе — они там и остаются.
              А если жёсткий диск полетит?)

              все будет потеряно
              А в сессии ничего важного и не должно быть. Максимальные потери здесь — содержимое корзины да и выход из аккаунта. А если настроить сохранение на диск, то и потеряется только сессионные данные за последние n секунд)
                Іван Клімчук
                04 августа 2021, 16:21
                +1
                У Redis есть режим персистентности, так что данные не будут потеряны. У нас в огромном проекте (не MODX) редис активно используется именно для сессий, потому что по другому не получается. К тому же кластер редиса хорошо масштабируется и позволяет запускать по 10 и более инстансов приложения, при этом пользователь не теряет своей сессии, даже если балансировщик подсунул ему другую машину.
                  Александр Мельник
                  04 августа 2021, 19:55
                  0
                  Уверен вы правы. Просто я еще не дорос до проектов, у которых есть балансировщики нагрузки и сопутствующие им проблемы.
                    Іван Клімчук
                    04 августа 2021, 21:51
                    +2
                    Вопрос не в дорос или нет, просто увидел в посте заблуждение, которое стало личным убеждением, и постарался его развеять.
                      Александр Мельник
                      05 августа 2021, 11:31
                      0
                      я имел ввиду, что выбор инструмента для решения задачи исходит из самой задачи. Возможно для таких систем как ваша, где запрос пользователя случайным образом отправляется на разные сервера, то выбор redis является правильным и удобным инструментом. Хотя не совсем понимаю, как это устроено. Редис работает одновременно на всех серверах и везде данные синхронизированы?
                        Іван Клімчук
                        05 августа 2021, 13:48
                        0
                        редис работает как единый сервис в amazon, а уже отдельные серверы с приложением к нему подключаются. Т.е. там одна общая база для всех.
    Сергей Шлоков
    30 июля 2021, 07:33
    +5
    Выступлю в роли Николая Ланца… Идея отличная!!! Но к реализации очень много вопросов.
    — для сессий создана новая таблица modx_smart_sessions, которая повторяет родную modx_sessions
    Зачем? Теперь лишняя таблица в базе болтается. Для таких целей используют миграции. В MODX их нет, но можно расширить схему.

    Писать в базу нефильтрованный USER_AGENT — это чтобы пощекотать себе нервы?

    Ну и про наследование в ООП советовал бы почитать.

    Режим «Николай Ланец» OFF. ))
      Наумов Алексей
      30 июля 2021, 09:20
      +2
      Так у меня и только beta версия только выпущена)))
      Но за здравую критику — спасибо
      Иван
      30 июля 2021, 12:44
      0
      Вообще хорошо бы понимать, что сессии должны создаваться только для авторизованных пользователей. Вряд ли все эти посетители, которые заходят на ваш сайт, регистрируются и авторизуются. Более разумно просто отказаться от использования таких дополнений как AjaxForm, который для каждого посетителя создает сессию. Тогда таблица вообще не будет пухнуть.
        Иван
        30 июля 2021, 13:10
        0
        Дополнение. Прочитал по ссылке и ужаснулся:
        При посещении какой-либо веб-страницы сайта, созданного на PHP, создается сессия.
        Видимо автор этого текста изучает PHP только в совокупности с MODX (и AjaxForm).

        В сессии хранятся данные, которые присущи только вашему визиту. Например, корзина товаров, информация о том, авторизовались ли вы для входа в личный кабинет и так далее.
        А если я не авторизовался и ничего не положил в корзину, то и сессия мне не нужна. На нормальных сайтах именно так и происходит.
          Наумов Алексей
          30 июля 2021, 14:38
          0
          Что значит только для авторизованных?..
          А корзина товаров? А если я товар «отложил», а если я перешел по реферальной ссылке на сайт, а если у нас правда что-то работает через ajax?
          Правильнее бы конечно создавать сессии когда они действительно нужны. Но MODX работает на своей волне, а кажется именно его мы здесь и обсуждаем.

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

          Давайте делать статичные странички на html!
            Иван
            30 июля 2021, 15:59
            0
            А корзина товаров? А если я товар «отложил»...
            Про это я уже написал. Зачем повторяться? Какой процент всех посетителей использует корзину товаров? Я думаю меньше 50%.

            а если у нас правда что-то работает через ajax?
            Для аякса необходимы сессии? Это что-то новенькое)

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

            Давайте делать статичные странички на html!
            Ну да, переписать дополнение или использовать другое не нужно. А нужно к этому дополнению городить кучу костылей))
              Иван
              30 июля 2021, 17:03
              0
              Уточню что я имею ввиду. Да, в MODX есть особенность, что если отключить «anonymous_sessions», то сессии будут работать только у авторизованных пользователей. В некоторых случаях это подходит (заставлять авторизовываться). Но важен также размер хранящейся информации в таблице сессии. Его нужно свести к минимуму + уменьшить время жизни сессии до суток (или даже 12 часов). Этого вполне достаточно для большинства сайтов. Но по-хорошему эту особенность с «anonymous_sessions» нужно исправить. Сессии должны создаваться только тогда, когда они нужны.
                Наумов Алексей
                02 августа 2021, 07:46
                0
                Так вот компонент и решает задачу:
                1. отдельно управлять временем жизни сессий для авторизованных пользователей (например, поставить им месяц);
                2. отдельно управлять временем жизни сессий ботов (к примеру, поставить им 3 часа);
                3. У всех остальных — ну пусть будет стандартная неделя.

                И на моих сайтах, за счет п.2. размер таблицы и объем данных уменьшился в десятки раз, т.к. именно сессии различных ботов составляли 90% записей в таблице.
                Дима Сайт old см. профиль
                01 августа 2021, 16:12
                0
                Ну да, переписать дополнение или использовать другое не нужно. А нужно к этому дополнению городить кучу костылей))
                @Иван хоть вы на первый взгляд и детально объяснили что там как должно быть на нормальных по вашему мнению сайтах, все же не понятно какую проблему вы видите в дополнении? Какие необходимые к нему костыли вы имеете в виду?

                Во времена повсеместного бума интернет-приватности и частичного отказа от cookies я вот хочу перенести в сессии некоторые настройки персонализации для незарегистрированных посетителей сайта (например открыто или закрыто боковое меню) и вообще сводить к минимуму использование cookies там где возможно.

                Короче, ИМХО тренд сейчас в сторону увеличения времени жизни сессий, а не уменьшению.

                Поэтому, если не «плакаться» что «anonymous_sessions» работает не так как хочется, а так, как решил мейнтейнер (хотя может и открыть ещё один issue для обсуждения?), то проблему с растущей базой надо как-то решать всё равно, а идея проверять user-agent и через него фильтровать сессии ботов это же прям похоже на решение!
                  Иван
                  03 августа 2021, 14:56
                  0
                  Я писал про дополнение «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. Автору большое спасибо! Конечно, готовые решения намного лучше когда в пакетах!
              Семён Кудрявцев
              03 августа 2021, 15:08
              0
              Потестил компонент, не работает функционал «Завершить все сеансы» — может быть имело смысл не создавать свою таблицу, а расширить существующую и тогда бы это работало. В итоге получаем ошибку —
              А так затея интересная, автору респект.
                Наумов Алексей
                03 августа 2021, 15:10
                0
                Точно, будем фиксить в следующих версиях)
                  Наумов Алексей
                  03 августа 2021, 15:49
                  0
                  Просто не выйдет…
                  MODX не умеет очищать сессии, если используется иной, отличный от modSessionHandler класс.

                  В процессоре проверяется настройка session_handler_class, и если там указано что-то не стандартное — сразу ошибка.

                  Как вариант — сделать свой пункт в меню для очистки сессий, а стандартный скрыть… ну и тогда нужно дописать процессор и т.п.
                    Сергей Шлоков
                    03 августа 2021, 17:08
                    +2
                    MODX не умеет очищать сессии, если используется иной, отличный от modSessionHandler класс.
                    Вот это шляпа. По хорошему нужно править это.
                    Самый простой выход — через js в админке менять хандлер у этого пункта меню, в котором указать свой процессор (поправленную копию системного процессора).
                      Наумов Алексей
                      04 августа 2021, 10:01
                      0
                      А самый правильный — интерфейс ISessionHandler с методом flushSessions, от которого наследуется уже modSessionHandler, и что бы именно он вызывался в процессоре.
                        Сергей Шлоков
                        04 августа 2021, 10:21
                        0
                        Правильный — да, реальный — нет. В двойку это не добавят, а тройка никогда не выйдет. Поэтому нужно рулить в рамках пакета.

                        П.С. К слову, я не сторонник С-ишных названий с префиксом I. Да и суффикс Interface, наверно, всё-таки лишний. По-современному должно быть так — интерфейс SessionHandler, а реализации — modSessionHandler, AntibotSessionHandler и т.п.
                          Наумов Алексей
                          04 августа 2021, 10:39
                          0
                          А абстрактный класс тогда как назвать, если SessionHandler занято интерфейсом? BaseSessionHandler?
                          Я с C# много работал N лет назад, в голове все это еще прочно сидит)
                            Сергей Шлоков
                            04 августа 2021, 10:46
                            0
                            BaseSessionHandler?
                            Подойдёт. Таким образом есть понимание, где интерфейс, а где реализация (при DI). Но как правило, одновременно интерфейсы и абстрактные классы используют редко. Для проекта достаточно абстрактного класса, для библиотеки — интерфейса. В общих случаях. Ну и пространства имён никто не отменял (для одинаковых названий).
                              Іван Клімчук
                              04 августа 2021, 16:26
                              +2
                              Вам PSR о чем-нибудь говорит? www.php-fig.org/bylaws/psr-naming-conventions/ — первые 3 пункта.
                  Василий Наумкин
                  04 августа 2021, 10:19
                  0
                  Отличная идея для дополнения!

                  Но я тоже за расширение оригинальной таблицы modx_sessions через свой плагин для добавления колонок.
                    Andrey
                    05 августа 2021, 17:55
                    +2
                    Госпаде! Спасибо Вам святой Вы человек! Пусть мана небесная сыплется бесконечно! Это реально ускоряет работу сайта, прям глаза открыли :DDD

                    П.С.
                    А еще закинул чуть чуть рублс для стимуляции подвигов, а это без сомнений подвиг!
                      Наумов Алексей
                      06 августа 2021, 09:52
                      +1
                      Ого, спасибо)
                        Andrey
                        11 августа 2021, 16:13
                        0
                        заметил один баг, он не прям совсем неприятный, но когда добавляешь допустим пользователя в определенную группу, например был он в группе: Users, а нужно еще добавить добавить в Bussines, то раньше при чистке КЕШа и перезагрузке прав, помогало не перелогиниваться пользователю и сразу пользоваться преимуществами новой группы, а сейчас нужно в базе удалять сессию.

                        Я может конечно чет не так понял… но это случилось после того как перешел на этот обработчик! Не подскажите в чем может быть проблемс?
                      Wassi Wassinen
                      19 февраля 2024, 17:21
                      0
                      @Наумов Алексей приветствую. Классное дополнение, вы молодец.

                      Есть вот такая ошибка в логах:

                      [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" для сохранения сессий (строка закомментирована). В чём может быть дело?
                        Николай Савин
                        19 февраля 2024, 17:49
                        0
                        Эта ошибка обычно означает попытку записать в сессию данные, в тот момент, когда не завершился еще прошлый запрос. То есть обращения к сессии через чур быстрые. Не успевает обработать. Сессии внутри баз данных немного медленнее работают, чем файловые сессии.
                          Wassi Wassinen
                          19 февраля 2024, 19:35
                          0
                          Похоже, придётся вернуться на файловые сессии.
                          Володя
                          19 февраля 2024, 19:48
                          0
                          А если перейти на modSessionHandler ошибки так же появляются?
                            Wassi Wassinen
                            19 февраля 2024, 21:55
                            0
                            Володя, спасибо за участие. Потестирую со стандартным.
                            Наумов Алексей
                            20 февраля 2024, 10:36
                            0
                            Привет, ну да, верно написал Николай, ошибка из-за того, что один запрос еще не завершен, а система отправляет второй. Посещаемость большая? Ошибка частая или разок проскочила?
                            Я, когда руки дойдут до smartSessions, попробую оптимизировать компонент, может побыстрее будет работать.
                              Wassi Wassinen
                              20 февраля 2024, 13:29
                              0
                              Алексей, здравствуйте.

                              Ошибки появляются несколько раз в день. Посещаемость +\- 10к в сутки. Но бывает больше. Иногда растёт скачкообразно. Видимо, в такие моменты и случается ошибка.
                              Видел похожий компонент от Володи. Для MODx3. modx.pro/components/24542. Там в комментах тоже были вопросы по оптимизации. Может быть поможет.

                              Спасибо за отзывчивость, Алексей. Будем ждать обновления.
                                Wassi Wassinen
                                26 февраля 2024, 14:27
                                0
                                И нужно исключить возможность вот такой ошибки :)

                                  Wassi Wassinen
                                  26 февраля 2024, 15:47
                                  0
                                  Как я понимаю, таблица начинает расти в прогрессии, если есть много контекстов. Так как данные пишет для каждого контекста, дублируя их. Интересно, это можно как-то оптимизировать?
                                    Wassi Wassinen
                                    26 февраля 2024, 16:12
                                    0
                                    И ещё вопрос: как дополнение понимает когда чистить таблицу — нет поля для хранения даты создания сессии. Или я как-то неправильно понял механизм работы?
                                      Наумов Алексей
                                      26 февраля 2024, 17:23
                                      0
                                      Поле access есть: см. исходники.

                                      … таблица начинает расти в прогрессии, если есть много контекстов
                                      В этом дополнении нет ничего нового, связанного с контекстами, по сравнению со стандартным sessionhandler. Основная цель дополнения — расширить таблицу сессий, чтобы в ней хранился user-agent. И если user-agent принадлежит боту — чистить такие сессии раньше, не хранить их долго.

                                      И нужно исключить возможность вот такой ошибки :)
                                      Эта ошибка возникла из-за того, что оказался поврежден файл с таблицей БД. Причина, по которой произошла данная ситуация, вероятно, связана с каким-то сбоем на сервере. К примеру, у меня раньше часто из-за нехватки памяти падал процесс mysql, и эти падения иногда заканчивались повреждением отдельных таблиц БД, весьма часто таблицы с сессией (потому что эта таблица каждый раз при открытии любой страницы сайта обновляется), но иногда и таблиц вроде site_content. Увеличение объема памяти решило в моем случае проблему с падающим mysql и повреждением таблиц.
                                        Наумов Алексей
                                        26 февраля 2024, 17:28
                                        0
                                        Я вообще зачем дополнение сделал:
                                        У моего сайта была посещаемость 300 человек в сутки. В неделю это 7*300=2100 человек. Сессии как раз неделю и хранились. Вот только в таблице сессий было не 2000 записей, как было бы ожидаемо, а около 100-200 тысяч. Когда я начал изучать вопрос — боты, одни боты! яндекс, гугл, просто wget какие-то, индексаторы картинок, парсеры… чего только не было) и что забавное — почти всегда каждый запрос генерил новую сессию, боты не держали её)) а итоге приходит яндекс бот на сайт, индексирует сайт, 3000 страниц — о-ппа и +3000 сессий. А кому они нужны?)
                                          Wassi Wassinen
                                          26 февраля 2024, 18:23
                                          0
                                          Да, полностью согласен с этим. Компонент нужный. Вы молодец :))
                                            Wassi Wassinen
                                            26 февраля 2024, 18:23
                                            0
                                            Алексей, а что делать, если таблица не очищается от сессий ботов? Хотя для ботов стоит время 10800.
                                              Наумов Алексей
                                              26 февраля 2024, 19:18
                                              0
                                              Ну а сигнатуры то ботов нужных прописаны в настройках (smartsessions_bot_signatures)?
                                              Это довольно индивидуальный параметр для каждого сайта. Если не очищается совсем — то gc не работает в php, с ним нужно копать, вот чтиво десятилетней давности: bezumkin.ru/sections/tips_and_tricks/2422
                                                Wassi Wassinen
                                                26 февраля 2024, 19:22
                                                0
                                                Благодарю за ответ. У вас эти настройки PHP (gc) как выставлены?
                                                  Наумов Алексей
                                                  27 февраля 2024, 10:48
                                                  0
                                                  честно говоря не помню, там и есть то пара их: что вообще включено, и делитель, у меня наверное 1/100 стоит
                                                    Wassi Wassinen
                                                    27 февраля 2024, 16:10
                                                    0
                                                    Да, так же выставил.
                                                  Wassi Wassinen
                                                  26 февраля 2024, 19:26
                                                  0
                                                  Сигнатуры прописаны.
                                                    Wassi Wassinen
                                                    26 февраля 2024, 20:12
                                                    0
                                                    И выдает вот такие ошибки:

                                                    [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)
                                                      Wassi Wassinen
                                                      26 февраля 2024, 20:29
                                                      0
                                                      И такие ошибки:

                                                      [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%' )
                                                        Наумов Алексей
                                                        27 февраля 2024, 10:48
                                                        0
                                                        странные ошибки

                                                        база то в порядке? таблица жива?
                                                          Wassi Wassinen
                                                          27 февраля 2024, 11:29
                                                          0
                                                          Да, таблицу чистил вручную по вхождениям сигнатур ботов)
                                                            Wassi Wassinen
                                                            28 февраля 2024, 02:27
                                                            0
                                                            Попробовал поискать ошибку. Яндекс показал это:

                                                            forums.modx.com/thread/103530/howto-remove-collection-from-custom-table
                                                              Wassi Wassinen
                                                              28 февраля 2024, 03:19
                                                              0
                                                              Я так понимаю, что дело вот в чём. У вас тип хранения InnoDB. В нём возможны так называемые Deadlock.
                                                              Что и происходит, судя по мониторингу MYSQL.

                                                                Wassi Wassinen
                                                                28 февраля 2024, 04:42
                                                                0
                                                                Теперь после удаления сайт падает наглухо :)
                                                                С такими ошибками в логах 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

                                                                Помогает только копирование файлов из бэкапа. В чем может быть дело?
                                                                  Наумов Алексей
                                                                  28 февраля 2024, 11:16
                                                                  0
                                                                  Сначала нужно вернуть настройку session_handler_class на modSessionHandler, и только потом удалять компонент, так должно быть все нормально
                                                                    Николай Савин
                                                                    28 февраля 2024, 19:10
                                                                    +1
                                                                    По хорошему этот пункт должен быть в качестве резолвера в компоненте.
                                                                    Наумов Алексей
                                                                    29 февраля 2024, 14:55
                                                                    +1
                                                                    Да, выпустил обновку. TODO в коде оказывается с самого начала на этот момент висел.
                                                                    Wassi Wassinen
                                                                    02 марта 2024, 15:54
                                                                    0
                                                                    Алексей, а с предыдущими ошибками о которых писал удалось разобраться?
                                                                    Наумов Алексей
                                                                    03 марта 2024, 17:34
                                                                    0
                                                                    Ну они плавающие, я не знаю, в чем причины. Я провел некоторую оптимизацию компонента, может что-то и исправилось
                                                Андрей Степаненко
                                                16 апреля 2024, 10:02
                                                +1
                                                Перенос из modx.pro/components/24542#comment-142930

                                                Проанализировал код

                                                1. Во время удаления сессий выполняется N запросов, если быть точным то сколько прописано сигнатур user agent столь и будет выполнено запросов
                                                2. Поле user_agent не индексное, то есть это будут медленные запросы



                                                Еще хотел узнать, зачем для ботов создавать сессию?
                                                И потом её удалять, целесообразность этого функционал не понимаю
                                                особенно с учетом тяжести запросов в цикле
                                                  Наумов Алексей
                                                  16 апреля 2024, 14:37
                                                  +1
                                                  Перенесу и свой ответ тогда уж!:
                                                  пару месяцев назад я переписал это всё… сейчас по другому, в github код доступен. Можно даже PR сделать!
                                                  Интересная мысль насчет целесообразности создания сессий для ботов… в принципе может они и не нужны… как вариант можно добавить соответствующую настройку в компонент. В общем мысль сохранил.
                                                    Дима Касаткин
                                                    16 апреля 2024, 17:44
                                                    0
                                                    Вам бы, коллеги, скооперироваться чтобы список ботов (user agent-ов) общий использовать для botAim и SmartSessions)

                                                    Предлагаю, если нужно, захостить его там же, где статистика установки компонентов, в надёжной инфраструктуре одного из крупных ДЦ. Я поспособствую!

                                                    Или выпустить список в качестве отдельного пакета, который наследовать, чтобы обновлять средствами MODX.

                                                    С каждым годом всё больше и больше проблем от ботов. Ваши решения (Алексея и Андрея) очень помогают, и необходимость в них только растёт!
                                                    Кровельный
                                                    13 мая 2024, 11:21
                                                    0
                                                    [2024-05-13 11:18:51] (ERROR @ Unknown0) PHP warning: Unknown: Cannot call session save handler in a recursive manner
                                                    Запись в базу работает, но в журнале эта запись. Кто-то уже сталкивался с этим нюансом?
                                                      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
                                                      73