2.09. Сессия
Сессия
Сессия — это ограниченный по времени логический контекст, в рамках которого происходит последовательность взаимосвязанных действий между участниками.
Участниками могут быть человек и программа, две программы, человек и устройство, или несколько устройств.
Сессия фиксирует факт начала взаимодействия, поддерживает его целостность на протяжении определённого периода и гарантирует корректное завершение. Это структурированное состояние, включающее учётные данные, права доступа, промежуточные результаты, идентификаторы ресурсов и метаданные, необходимые для продолжения работы без повторной инициализации.
Основная задача сессии — преодолеть ограничение безсостоятельности протоколов, построенных на модели «запрос — ответ». Многие протоколы, особенно на нижних уровнях сетевого стека, не сохраняют информацию о предыдущих обращениях. Каждый запрос технически независим. Однако в реальных сценариях действия редко бывают изолированными. Пользователь заходит на сайт, проходит аутентификацию, просматривает несколько страниц, добавляет товар в корзину, оформляет заказ — все эти шаги логически связаны. Без сессии каждое действие требовало бы повторного ввода логина и пароля, повторной загрузки профиля, повторного согласования параметров. Сессия выступает как «нить памяти», проходящая через всю цепочку операций.
Концепция сессии зародилась в эпоху интерактивных терминалов и многопользовательских систем. В те времена пользователь физически подключался к компьютеру через последовательный порт или сетевое соединение — начало сессии совпадало с установлением связи, её завершение — с разрывом. Позже, с приходом клиент-серверных архитектур и особенно веба, связь стала прерывистой. HTTP изначально задумывался как протокол для передачи статических документов — каждый клик порождал отдельное TCP-соединение, которое сразу же закрывалось. Такая модель эффективна для простых задач, но не поддерживает сложное, многошаговое взаимодействие. Чтобы компенсировать это, разработчики стали вводить механизмы сохранения состояния между запросами. Появились cookies, серверные хранилища, идентификаторы сессий — технические решения, реализующие идею логической целостности в физически разорванной среде.
Сессия обладает чёткими границами. Она создаётся в момент, когда система распознаёт начало осмысленной последовательности действий. Это может быть вход пользователя по логину и паролю, вызов метода beginTransaction(), инициализация FTP-соединения, или получение валидного JWT-токена. С этого момента система выделяет ресурсы: память для хранения данных, файловые дескрипторы, сетевые буферы, записи в журналах аудита. Внутри сессии фиксируется информация: кто инициировал взаимодействие, когда оно началось, какие права подтверждены, какие операции уже выполнены, какие объекты заняты. Всё это — часть сессионного контекста.
Временные характеристики сессии — её длительность, время неактивности, момент истечения — управляются политиками. Сервер может задавать максимальное время жизни сессии, например, 30 минут с момента создания. Другой подход — установка таймаута неактивности: если в течение 15 минут не поступало ни одного запроса, сессия автоматически уничтожается. Некоторые системы поддерживают продление сессии: каждый новый запрос с действительным идентификатором сдвигает момент окончания на фиксированный интервал. Длительность выбирается, исходя из баланса между удобством и безопасностью. Короткие сессии снижают риск несанкционированного доступа при утечке идентификатора, но требуют частой повторной аутентификации. Длинные сессии удобны для пользователей, но увеличивают «окно уязвимости». В высоконагруженных системах сессии часто ограничиваются строго — чтобы предотвратить накопление «мёртвых» контекстов, которые потребляют ресурсы, но не используются.
В классическом веб-приложении сессия создаётся на сервере после успешной проверки подлинности. Сервер генерирует уникальный идентификатор — обычно случайную строку достаточной длины и энтропии (например, 128-битный UUID в base64-кодировке). Этот идентификатор сохраняется в серверном хранилище: в оперативной памяти, в распределённом кэше (Redis, Memcached), или в базе данных. Одновременно идентификатор передаётся клиенту — чаще всего через HTTP-заголовок Set-Cookie, где он сохраняется в cookie браузера. Последующие запросы от того же клиента включают этот идентификатор в заголовке Cookie. Сервер извлекает его, находит соответствующий сессионный объект и восстанавливает контекст. В сессии могут храниться: идентификатор пользователя, роль, настройки интерфейса, состояние корзины, временные файлы, результаты поиска, токены внешних систем. Всё, что помогает избежать повторных вычислений и сохранить непрерывность опыта.
Однако такая модель — stateful: сервер несёт ответственность за хранение и управление состоянием. Она требует синхронизации между узлами в кластере, механизмов восстановления при сбое, аккуратного распределения нагрузки (чтобы последующие запросы попадали на тот же сервер, где хранится сессия — sticky sessions). Эти сложности побудили к развитию альтернативных подходов, особенно в области интеграции программных систем.
В интеграционном взаимодействии — когда одна программа вызывает методы другой через сеть — понятие сессии приобретает иное значение. Здесь речь идёт не о человеке, а о машинах, обменивающихся структурированными сообщениями. Сессия служит для объединения логически связанных операций, даже если они разнесены во времени и требуют нескольких раундов обмена. Такой контекст может быть организован двумя способами: явно или неявно.
Явная сессия требует чёткой последовательности: сначала вызывается метод открытия (openSession, login, init), который возвращает уникальный идентификатор сессии. Этот идентификатор включается во все последующие запросы, пока сессия активна. По завершении работы вызывается метод закрытия (closeSession, logout, terminate). Такой подход характерен для протоколов, ориентированных на состояние: FTP, SMB, SOAP с расширениями WS-*, некоторые реализации gRPC с поддержкой потоков, а также legacy-системы типа CORBA или DCOM. В FTP, например, клиент сначала устанавливает TCP-соединение, затем отправляет команды USER и PASS, получает подтверждение — и только после этого может выполнять LIST, RETR, STOR. Весь этот цикл — одна сессия. Если соединение обрывается, сессия автоматически прекращается. Если клиент хочет продолжить, он должен пройти аутентификацию заново.
Преимущество явной сессии — точный контроль. Система знает, сколько сессий активно, какие ресурсы заняты, кто и как долго работает. Это критично для сценариев, где требуется гарантия последовательности: передача большого файла по частям, выполнение многошаговой финансовой транзакции, синхронизация состояний в реальном времени. Однако стоимость этого контроля высока: сервер должен выделять память, отслеживать таймауты, обеспечивать отказоустойчивость (например, через репликацию сессионных данных). Масштабирование таких систем — нетривиальная инженерная задача.
Неявная сессия — более современный и лёгкий подход. Он применяется в архитектурах, построенных на принципе безсостоятельности (stateless), таких как REST, GraphQL, или event-driven системы. В этом случае сервер не хранит контекст между запросами. Каждый запрос полностью самодостаточен: он содержит всю необходимую информацию для его обработки — включая учётные данные, параметры операции, идентификаторы ресурсов. Учётные данные передаются в заголовках (например, Authorization: Bearer <токен>), в теле сообщения или в цифровой подписи. Логическая связь между запросами поддерживается на уровне клиента или промежуточных компонентов: мобильное приложение может хранить токен в защищённом хранилище и прикреплять его к каждому вызову; API Gateway может агрегировать несколько внутренних вызовов в один внешний запрос, сохраняя контекст аутентификации; оркестратор процессов (BPM-движок) может вести журнал шагов транзакции, не полагаясь на серверное состояние.
Токены — ключевой элемент неявной сессии. JWT (JSON Web Token), например, представляет собой компактный, самодостаточный объект, закодированный в base64url. Он содержит заголовок (алгоритм подписи), полезную нагрузку (идентификатор пользователя, роль, время выдачи, срок действия) и криптографическую подпись. Сервер проверяет подпись с помощью известного ключа и принимает решение на основе данных внутри токена. Никакого поиска в базе не требуется — проверка происходит локально, за миллисекунды. Такой токен сам по себе — временный контекст доверия, встроенный в каждый запрос.
Закрытие сессии — это процедура освобождения ресурсов и прекращения действия контекста доверия. В явной модели это вызов метода closeSession, который удаляет запись на сервере, закрывает соединения, сбрасывает буферы, записывает событие в журнал. В неявной модели, где сервер не хранит состояние, «закрытие» реализуется через инвалидацию учётных данных. Токен объявляется недействительным — например, добавлением его идентификатора (jti) в чёрный список (deny list) или через механизм отзыва (Token Revocation в OAuth 2.0). API Gateway или аутентификационный сервис проверяют каждый входящий токен не только на срок действия и подпись, но и на наличие в списке отозванных. Это позволяет мгновенно прекратить доступ даже при наличии валидного, но скомпрометированного токена.
Инвалидация особенно важна в случае утечки. Если злоумышленник перехватывает идентификатор сессии или токен, у него появляется возможность действовать от имени легального пользователя. Чем дольше такой токен остаётся активным, тем больше ущерба можно нанести. Поэтому системы безопасности предусматривают экстренные процедуры: отзыв по запросу администратора, отзыв при смене пароля, отзыв при подозрительной активности (например, вход с нового устройства или из другой страны). Некоторые токены имеют короткий срок жизни (minutes) и используют refresh-токены с более длительным сроком, но строгим контролем хранения — так достигается баланс между удобством и защитой.
Выбор между явной и неявной сессией определяется требованиями сценария. Stateless-подход предпочтителен в большинстве современных распределённых систем: он упрощает горизонтальное масштабирование (любой узел может обработать любой запрос), повышает отказоустойчивость (падение одного сервера не ведёт к потере состояния), ускоряет разработку и тестирование (каждый запрос изолирован). RESTful API, микросервисы, serverless-функции — все они строятся на этом принципе.
Однако есть случаи, где stateful-модель остаётся оправданной. Это сценарии с высокой степенью взаимозависимости операций: загрузка файла в 100 частей, когда сервер должен убедиться, что все фрагменты пришли в правильном порядке и ни один не потерян; интерактивные сессии в реальном времени (видеоконференции, совместное редактирование документов); сложные транзакции, требующие двухфазного коммита (2PC) или компенсирующих действий (Sagas); интеграция с унаследованными системами, которые не поддерживают токены и требуют постоянного соединения.
Сессии в конкретных протоколах и технологиях
Разные протоколы и платформы реализуют концепцию сессии по-своему — в зависимости от целей, исторического наследия и требований к производительности и безопасности. Рассмотрим несколько ключевых случаев.
HTTP и cookie-based сессии — классика веба. Сервер создаёт объект сессии, генерирует идентификатор, сохраняет его на стороне сервера и отправляет клиенту через заголовок Set-Cookie. Браузер автоматически возвращает этот идентификатор в каждом последующем запросе к тому же домену. Такой подход прост и универсален, но имеет ограничения: cookie привязаны к домену и пути, их размер ограничен (обычно 4 КБ на cookie, до 50 штук на домен), передача происходит автоматически — в том числе в запросах к изображениям, стилям, скриптам, что может привести к нецелевому раскрытию идентификатора. Для защиты применяются флаги: HttpOnly (запрет доступа из JavaScript), Secure (передача только по HTTPS), SameSite (контроль отправки при межсайтовых запросах). Эти меры снижают риски CSRF и XSS-эксплуатации, но не устраняют их полностью.
JWT и токен-ориентированные сессии — доминирующий подход в современных API. Токен создаётся после аутентификации и содержит в себе всю необходимую информацию: субъект (например, user_id), роль, область действия (scope), время выдачи (iat), срок окончания (exp). Подпись гарантирует целостность и подлинность. Сервер не хранит токен — он лишь проверяет его при каждом запросе. Это позволяет легко масштабировать бэкенд: любой экземпляр сервиса может обработать запрос, не обращаясь к общему хранилищу. Однако у такого подхода есть нюансы. Токен нельзя «отозвать» до истечения срока, если не вводить дополнительные механизмы — например, список отозванных токенов (deny list) или короткоживущие access-токены в паре с долгоживущими refresh-токенами. Refresh-токен хранится в защищённом хранилище (например, HTTP-only cookie с флагом Secure и SameSite=Strict) и используется только для получения новой пары токенов. После успешного обновления предыдущий refresh-токен инвалидируется, что предотвращает повторное использование.
OAuth 2.0 и OpenID Connect — стандарты делегированной авторизации и аутентификации. Здесь сессия существует на нескольких уровнях одновременно. Пользователь имеет сессию в Identity Provider (например, Google, Keycloak): он вошёл один раз — и теперь может получать токены для разных клиентских приложений без повторного ввода пароля. Клиентское приложение (например, мобильное) имеет собственную сессию с пользователем — оно управляет access- и refresh-токенами, обновляет их, реагирует на ошибки вида invalid_token. Resource Server, в свою очередь, проверяет каждый входящий токен, не зная ничего о пользовательской сессии — он доверяет только подписи и данным внутри токена. Такая многоуровневая модель позволяет разделять зоны ответственности: Identity Provider отвечает за подтверждение личности, клиент — за удобство взаимодействия, сервер — за защиту ресурсов.
WebSocket — протокол двунаправленной связи в реальном времени. Сессия в WebSocket начинается с HTTP-рукета Upgrade, после которого устанавливается постоянное TCP-соединение. В отличие от HTTP, где каждый запрос независим, WebSocket-соединение — это одна долгоживущая сессия. В ней можно отправлять множество сообщений в обе стороны без накладных расходов на установку соединения. Сервер и клиент хранят состояние соединения: открыт ли канал, какие подписки активны, какие данные уже переданы. Такая сессия требует аккуратного управления: при потере сети клиент должен пытаться переподключиться, сервер — корректно обрабатывать разрывы и очищать ресурсы. Часто поверх WebSocket строится собственный протокол с идентификаторами запросов, подтверждениями доставки и восстановлением состояния после переподключения — что создаёт ещё один уровень сессионного контекста.
FTP и legacy-протоколы — пример stateful-взаимодействия в чистом виде. FTP использует два канала: управляющий (для команд USER, PASS, CWD, LIST) и передачи данных (для содержимого файлов). Сессия существует всё время, пока открыто управляющее соединение. Команды строго упорядочены: нельзя выполнить STOR до успешного PASS. Сервер ведёт внутреннее состояние: текущая директория, права доступа, открытые файловые дескрипторы. Если клиент неактивен дольше таймаута, сервер разрывает соединение и освобождает ресурсы. Такая модель надёжна для простых сценариев, но плохо масштабируется и уязвима к атакам типа «захват сессии» (session hijacking), особенно в незашифрованном режиме.
gRPC и потоковые вызовы — гибридный подход. Основная модель gRPC — stateless: каждый вызов RPC независим. Но протокол поддерживает три вида потоков: от клиента, от сервера и двунаправленные. В двунаправленном потоке клиент и сервер могут обмениваться множеством сообщений в рамках одного вызова. Это создаёт локальную, временную сессию: сервер может хранить состояние для конкретного потока (например, буфер для агрегации данных), но после завершения потока — состояние удаляется. Такой подход эффективен для сценариев вроде передачи аудио/видео потока, синхронизации в реальном времени или постраничной загрузки с фильтрацией на лету.
Сессия в вебе и в мобильных приложениях: различия в реализации
Хотя концепция одинакова, техническая реализация сессии в браузере и в нативном приложении различается.
В вебе основной транспорт — cookie. Они управляются браузером, автоматически прикрепляются к запросам, имеют строгие политики безопасности. Однако их применение ограничено: нельзя использовать cookie в CORS-запросах без явного разрешения, они не работают в Web Workers напрямую, их сложно контролировать при переходе между поддоменами. Поэтому многие SPA (одностраничные приложения) отказываются от cookie в пользу явного хранения токенов в localStorage или sessionStorage — но это повышает риски XSS, так как JavaScript получает прямой доступ к учётным данным.
Мобильные приложения не имеют встроенного механизма вроде cookie. Разработчик сам решает, где и как хранить идентификатор сессии или токен: в защищённом хранилище операционной системы (Keychain на iOS, EncryptedSharedPreferences на Android), в памяти приложения (пока оно не убито), или в файлах с шифрованием. Такой контроль даёт гибкость: можно реализовать «запомнить меня», можно хранить несколько сессий для разных аккаунтов, можно легко очищать данные при выходе. Но вместе с этим приходит ответственность: ошибка в реализации (например, сохранение токена в открытом виде в SharedPreferences) может привести к утечке.
Мобильные клиенты также чаще используют долгоживущие сессии. Пользователь заходит один раз — и работает неделями. Чтобы сохранить безопасность, применяются дополнительные меры: привязка токена к устройству (через fingerprint: модель, серийный номер, MAC-адрес — если доступен), регулярная переаутентификация при критических операциях (платёж, смена пароля), фоновая проверка состояния сессии через silent refresh.
Сессия и безопасность: как её защищают и как используют против системы
Сессия — это точка доверия. Её компрометация означает передачу полномочий злоумышленнику. Поэтому защита сессионных механизмов — одна из центральных задач информационной безопасности.
Основные угрозы:
-
Перехват идентификатора — через незашифрованный трафик (HTTP), уязвимости в клиентском коде (XSS), подделку сетевых пакетов (MITM). Решение: обязательное использование HTTPS, флаги
SecureиHttpOnlyдля cookie, хранение токенов вне JavaScript-доступа. -
Предсказуемость идентификатора — если идентификатор генерируется слабым алгоритмом (например, последовательные числа), злоумышленник может подобрать чужую сессию. Решение: криптографически стойкие генераторы случайных чисел (CSPRNG), достаточная длина (минимум 128 бит энтропии).
-
Фиксация сессии (Session Fixation) — атакующий заставляет жертву использовать заранее известный идентификатор (например, передаёт ссылку с
?sessionid=abc). После входа жертвы сессияabcстановится валидной — и атакующий получает доступ. Решение: смена идентификатора сессии после успешной аутентификации. Новый идентификатор выдаётся, старый инвалидируется. -
Межсайтовая подделка запроса (CSRF) — сайт-злоумышленник заставляет браузер жертвы отправить запрос к уязвимому сервису, используя действующую сессию. Решение: anti-CSRF-токены (уникальный токен в форме или заголовке, проверяемый сервером), флаг
SameSite=StrictилиLaxдля cookie, проверка заголовкаOrigin. -
Утечка через логи, кэш, историю браузера — идентификатор, попавший в URL (
?token=xyz), может сохраниться в истории, логах сервера, прокси-серверах. Решение: передача токенов только в заголовках (Authorization), никогда — в URL.
Защита строится на многоуровневом подходе: криптография, политики хранения, валидация, мониторинг. Например, система может вести журнал активных сессий с привязкой к IP, User-Agent, геолокации. При входе с нового устройства — требовать подтверждение по SMS или через приложение-аутентификатор. При резком изменении параметров (вход из другой страны за 10 минут) — автоматически инвалидировать сессию и отправить уведомление.
Продление, миграция и восстановление сессий
Жизнь сессии редко укладывается в жёсткие рамки. Пользователь может уйти на обед, но вернуться через 40 минут; мобильное приложение может быть убито системой из-за нехватки памяти; сетевое соединение может оборваться и восстановиться. Чтобы не заставлять пользователя проходить аутентификацию заново, системы реализуют механизмы продления и восстановления.
Продление по активности — стандартная практика. Каждый валидный запрос сдвигает момент окончания сессии на фиксированный интервал (например, +15 минут). Это работает для интерактивных сценариев, но требует осторожности: если злоумышленник получает идентификатор, он тоже может продлевать сессию, делая «ping» каждые 14 минут. Поэтому часто вводят жёсткий лимит: «максимум 8 часов непрерывной сессии, независимо от активности».
Silent refresh — техника, применяемая в SPA и мобильных приложениях. Когда access-токен близок к истечению, клиент в фоне (без участия пользователя) обращается к endpoint /token с refresh-токеном и получает новую пару. Пользователь не замечает обновления — сессия «течёт» непрерывно. Если refresh-токен недействителен (отозван, просрочен), приложение перенаправляет на страницу входа.
Миграция сессий между устройствами — растущий тренд. Пользователь начинает оформлять заказ на телефоне, а завершает на компьютере. Для этого используется синхронизация состояния через облачный аккаунт: данные корзины, форма ввода, текущий шаг — всё сохраняется на сервере и привязывается к учётной записи, а не к конкретной сессии. Тогда сессия становится лишь временным «окном доступа» к долгоживущему состоянию.
Оффлайн-сессии — сложная тема. Мобильные и десктопные приложения могут работать без сети, сохраняя действия локально, а затем синхронизируя их при восстановлении связи. Здесь сессия как таковая не существует (нет связи с сервером), но логика сессионного контекста переносится на клиент: приложение знает, что пользователь «вошёл», какие данные ему доступны, какие операции можно выполнять. После синхронизации сервер проверяет, не изменились ли права или состояние данных — и применяет компенсирующие действия, если обнаружено несоответствие.
Логирование, аудит и анализ сессий
Сессия — богатый источник данных для аналитики и безопасности.
-
Аудит — каждая сессия логируется: время начала и окончания, идентификатор пользователя, IP-адрес, User-Agent, список выполненных операций, время завершения (нормальное или по таймауту). Это позволяет восстановить цепочку действий при расследовании инцидента.
-
Мониторинг — системы отслеживают количество активных сессий, среднюю длительность, частоту таймаутов. Резкий рост «зависших» сессий может указывать на атаку типа DoS или ошибку в клиентском коде.
-
Аналитика поведения — как долго пользователи остаются в системе, на каком шаге чаще всего уходят, сколько операций выполняют за сессию. Эти метрики помогают улучшать UX.
-
Обнаружение аномалий — машинное обучение может выявлять подозрительные паттерны: сессия из редкой страны, нехарактерная последовательность действий (например, вход → смена email → смена пароля за 10 секунд), одновременные сессии с разных континентов. Такие события триггерят дополнительную проверку или блокировку.
Данные о сессиях часто интегрируются в SIEM-системы (Security Information and Event Management), где коррелируются с другими событиями: неудачные входы, изменения конфигурации, доступ к чувствительным данным.
Сессия в интеграционных шинах и ESB (Enterprise Service Bus)
В крупных корпоративных системах редко бывает прямое «точка-в-точку» взаимодействие. Вместо этого используется промежуточный слой — интеграционная шина, такая как Apache Camel, MuleSoft, IBM Integration Bus или ELMA365 Интеграция. В этом контексте сессия — это сквозной идентификатор операционного контекста, сопровождающий сообщение на всём пути от источника до получателя.
Интеграционная шина получает входящий запрос (например, от веб-сервиса), извлекает или генерирует идентификатор сессии, и присваивает его внутреннему маршруту (route). Далее сообщение может проходить через десятки этапов: валидация, трансформация, вызов внешнего API, запись в очередь, обогащение данными из справочника, логирование. На каждом этапе компоненты могут читать или дописывать информацию в сессионный контекст — например, добавить идентификатор транзакции, зафиксировать время входа в этап, сохранить промежуточный статус.
Такой подход обеспечивает сквозную трассировку. Если на десятом шаге возникает ошибка, система может точно сказать: в какой сессии произошёл сбой, какие данные были на входе, какие сервисы уже отработали, какие изменения внесены. Идентификатор сессии логируется везде — в application-логах, в мониторинге (например, Jaeger или Zipkin), в базе аудита. Это критично для диагностики нестабильных интеграций.
В шинах часто используется корреляционный идентификатор (correlation ID) — он и есть техническое воплощение сессии на уровне интеграции. Его генерируют один раз — на границе системы (например, API Gateway), и передают во все внутренние вызовы через заголовки (X-Correlation-ID, traceparent). Даже если часть логики уходит в асинхронную очередь (Kafka, RabbitMQ), корреляционный ID сохраняется в метаданных сообщения. Так достигается целостность: все события, относящиеся к одному пользовательскому действию («оформить заказ»), объединяются в единую цепочку, несмотря на распределённость, параллелизм и отложенную обработку.
Важно, что в ESB сессия часто не связана с пользователем напрямую. Она может соответствовать одному REST-запросу, одному файлу выгрузки, одному пакету данных из 1С. Это логический контекст операции, а не контекст доверия. Аутентификация и авторизация — отдельный слой, который может использовать собственную сессию (например, OAuth-токен), но корреляционный ID существует независимо от него.
Сессия в оркестрации процессов
В системах управления бизнес-процессами (BPM-движки вроде Camunda, Flowable, ELMA BPM) сессия приобретает ещё более насыщенное значение. Здесь сессия — это экземпляр процесса (process instance), который запускается по событию и живёт до своего естественного завершения или принудительной остановки.
Процесс может включать десятки шагов: автоматические действия (вызов API, расчёт суммы), ручные задачи (согласование руководителем), таймеры (ожидание оплаты 3 дня), шлюзы (ветвление по условиям). Каждый экземпляр процесса имеет уникальный идентификатор, сохраняет текущее состояние (на каком шаге находится), хранит переменные (номер заказа, сумма, ФИО клиента), историю переходов и привязку к инициатору.
Такая «процессная сессия» долгоживущая — от нескольких секунд до нескольких месяцев. Она переживает перезагрузки сервера, так как состояние сериализуется в базу данных. При возобновлении движок загружает данные и продолжает выполнение с того места, где остановился. Это делает BPM-сессию устойчивой к сбоям, но требует аккуратного проектирования: нельзя хранить в переменных процесса конфиденциальные данные (пароли, токены), нельзя предполагать, что объекты в памяти останутся неизменными — всё должно быть восстанавливаемо из персистентного хранилища.
Процессная сессия может порождать подпроцессы — вложенные сессии. Например, основной процесс «Обработка заявки» вызывает подпроцесс «Проверка контрагента», который сам по себе имеет свой жизненный цикл, переменные и логику. Это позволяет повторно использовать блоки логики и строить иерархические модели.
Ключевое отличие от веб-сессии: процессная сессия не умирает по таймауту неактивности. Она ждёт события — будь то действие пользователя, приход ответа от внешней системы или срабатывание таймера. Её завершение — результат бизнес-логики, а не ограничения инфраструктуры.
Сессия и транзакция
Часто сессию путают с транзакцией. Это смежные, но принципиально разные понятия.
Транзакция — это группа операций, выполняемых как единое целое: либо все изменения зафиксированы, либо ни одно. Она гарантирует атомарность, согласованность, изолированность и долговечность (ACID). Транзакция коротка — обычно миллисекунды или секунды. Она живёт в рамках одного вызова к базе данных или распределённой системе (через 2PC, Saga и т.п.).
Сессия — это контекст, в котором может происходить много транзакций. Пользователь заходит в систему (открытие сессии), создаёт заказ (транзакция 1: запись в orders), резервирует товары (транзакция 2: обновление inventory), отправляет уведомление (транзакция 3: запись в notifications). Все эти транзакции логически связаны, но технически независимы. Если третья упадёт, первые две не откатятся автоматически — разве что будет запущена компенсирующая операция (например, отмена резервации).
Сессия может управлять границами транзакций. Например, в Java EE приложении сессионный Bean может объявлять метод как @Transactional — тогда контейнер автоматически начнёт и завершит транзакцию при входе и выходе из метода. Но сама сессия Bean (stateful session bean) живёт дольше, храня данные между вызовами.
В распределённых системах границы стираются. Saga-паттерн, например, моделирует долгую «транзакцию» через цепочку локальных транзакций и компенсирующих действий. Каждый шаг Saga — это отдельная транзакция, но вся последовательность объединена в логическую единицу, управляемую оркестратором. Такая единица — это гибрид сессии и транзакции: она долгая, распределённая, идемпотентная, с явным управлением откатами.