Spring Session - асинхронная обработка вызовов - PullRequest
0 голосов
/ 29 сентября 2018

Управляет ли Spring Session управление асинхронными вызовами?

Скажите, что у нас есть несколько контроллеров, и каждый из них читает / записывает различные атрибуты сеанса.Будет ли проблема параллелизма, поскольку объект сеанса целиком записывается / читается на внешние серверы / читается на них, а не только с атрибутами?

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

Когда мы используем объект сеанса из контейнера, мы никогда не сталкивались с этой проблемой ... предполагая, что это прямой атрибутустановить / получить происходящее прямо в объекте сеанса в памяти.

Ответы [ 2 ]

0 голосов
/ 21 декабря 2018

Этот вопрос очень похож на ваш последний вопрос .И вы должны прочитать мой ответ на этот вопрос, прежде чем читать мой ответ / комментарии здесь.

Предыдущий ответ (и понимание), размещенный анонимным пользователем, является довольно точным.

Каждый раз, когда у вас есть высококонкурентное (веб) приложение / среда, где поступает много разных одновременных HTTP-запросов, обращающихся к одному и тому же HTTP-сеансу, всегда есть вероятность потерянных обновлений вызвано условиями гонки между конкурирующими параллельными HTTP-запросами.Это связано с самой природой контейнера сервлетов (например, Apache Tomcat или Eclipse Jetty), поскольку каждый HTTP-запрос обрабатывается отдельным потоком и внутри него.

Не только объект сеанса HTTP, предоставляемыйконтейнер сервлетов должен быть поточно-ориентированным, но также и все объекты домена приложения, которые ваше веб-приложение помещает в сеанс HTTP.Итак, помните об этом.

Кроме того, большинство реализаций сеансов HTTP, таких как Apache Tomcat или даже реализация сеансов Spring Session , поддерживаются различными поставщиками управления сеансами (например, Spring).Данные сеанса Redis или Spring Session Data GemFire ​​) широко используют «дельты» для отправки только изменений (или различий) в состояние сеанса, сводя к минимуму вероятность потери обновляет из-за условий гонки .

Например, если сеанс HTTP в настоящее время имеет ключ / значение атрибута 1/A и HTTP-запрос 1 (обработанный потоком 1) считываетсеанс HTTP (только с 1/A) и добавляет атрибут 2/B, в то время как другой параллельный запрос HTTP 2 (обработанный потоком 2) считывает тот же сеанс HTTP по идентификатору сеанса (видя то же самое начальное состояние сеанса с 1/A), и теперь он хочет добавить 3/C, тогда, как разработчики веб-приложений, мы ожидаем, что конечный результат и состояние сеанса HTTP будут, после запроса 1& 2 в темах 1 и 2 завершены, включая атрибуты: [1/A, 2/B, 3/C].

Однако, если 2 (или даже больше) конкурирующих HTTP-запроса модифицируют, скажем, атрибут HTTP sessoin 1/A и HTTP-запрос / поток1 хочет установить для атрибута 1/B, а конкурирующий HTTP-запрос / Поток 2 хочет установить для того же атрибута 1/C, тогда кто выигрывает?

Ну, получается, последние 1 побед, или, скорее,последний поток, записывающий состояние сеанса HTTP, выигрывает, и результатом может быть 1/B или 1/C, который является неопределенным и зависит от капризов планирования, задержки в сети, нагрузки и т. д. и т. д. Фактически этоПочти невозможно предположить, что произойдет, гораздо реже случается.

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

Но если мы подумаем об этом в производственном контексте, где у вас может быть, скажем, несколько сотен экземпляров веб-приложений, распределенных по нескольким физическим машинам, или виртуальным машинам, или контейнерам, и т. Д., Балансировка нагрузки выполняется каким-либо балансировщиком / устройством сетевой нагрузки, изатем добавим тот факт, что многие веб-приложения сегодня являются «одностраничными приложениями», очень сложными, не тупыми (уже не тонкими), но толстыми клиентами с вызовами JavaScript и AJAX, и мы начинаем понимать, что этот сценарий гораздо более вероятен, особеннов сильно загруженном веб-приложении;думаю, Amazon или Facebook.Не только много одновременных пользователей, но и много одновременных запросов от одного пользователя с учетом всех динамических асинхронных вызовов, которые может выполнять веб-приложение.

Тем не менее, как указал наш анонимный пользователь, это не оправдывает веб-приложение.разработчик ответственно проектирует и кодирует наше веб-приложение.

В целом, я бы сказал, что HTTP-сеанс должен использоваться только для отслеживания очень минимальной (то есть по количеству) и необходимой информации для поддержания хорошего пользовательского опыта и сохранения надлежащего взаимодействия между пользователем и приложением при переходе пользователя черезразличные части или фазы веб-приложения, такие как отслеживание предпочтений или элементов (в корзине).Как правило, сеанс HTTP не должен использоваться для хранения «транзакционных» данных.Должно быть так, чтобы попасть в беду.Сеанс HTTP должен быть в первую очередь структурой данных с интенсивным чтением (а не с интенсивной записью), особенно потому, что сеанс HTTP может и, скорее всего, будет доступен из нескольких потоков.

Конечно, разные хранилища данных (например,Redis и даже GemFire) предоставляют механизмы блокировки.GemFire ​​даже предоставляет транзакции на уровне кэша, что является очень тяжелым и не подлежащим обсуждению, неуместным при обработке веб-взаимодействий, управляемых объектом сеанса HTTP и с ним (не путать с транзакциями).Даже блокировка может привести к серьезному конфликту и задержке приложения.

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

Пища для размышлений!

0 голосов
/ 30 сентября 2018

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

Это не распространенный (и ИМХО разумный) сценарий для сеанса, поэтому такие проекты, как spring-data-redis или spring-data-gemfire не будут поддерживать его "из коробки".

Хорошая новость заключается в том, что весенняя сессия была построена с учетом гибкости, поэтому вы, конечно, можете достичь того, чего хотите.Вы можете реализовать собственную версию SessionRepository и вручную синхронизировать (например, через распределенные блокировки Redis) соответствующие методы.Но, прежде чем сделать это, проверьте свой дизайн и убедитесь, что вы используете сеанс для правильного задания хранения данных.

...