Сессионные бобы без сохранения состояния и синглтон-сессия - PullRequest
27 голосов
/ 06 января 2010

В учебнике Java EE 6 написано:

Чтобы повысить производительность, вы можете выбрать сессионный компонент без сохранения состояния, если он имеет одну из следующих характеристик:

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

Сессионные компоненты синглтона подходят в следующих случаяхобстоятельства:

  • Состояние должно быть общим для всего приложения.
  • Одному корпоративному бину требуется одновременный доступ к нескольким потокам.
  • Приложению требуется предприятиеbean-компонент для выполнения задач при запуске и завершении работы приложения.
  • Bean-компонент реализует веб-службу.

Но что использовать, если:

  • никакое состояние не должно совместно использоваться приложением
  • один корпоративный компонент может быть доступен нескольким потокам одновременно
  • нет необходимости выполнять задачи при запуске или сокращении

Скажем, например, у меня есть служба входа в систему со следующим интерфейсом:

public interface LoginService {
  boolean authenticate(String user, String password);
}

Должна ли она быть аннотирована @Singleton или @Stateless?Каковы преимущества одного и другого?Что если LoginService необходимо ввести EntityManager (который будет использоваться одновременно)?

Добавление: Я имею в виду аналог Java EE бинов службы Spring, которые являются одиночными объектами без сохранения состояния.Если я правильно понимаю, что аналог Java EE - это сессионные компоненты @Stateless, а компоненты @Singleton используются для настройки приложения при запуске или очистки при завершении работы или для хранения объектов всего приложения.Это правильно?

Ответы [ 8 ]

13 голосов
/ 06 января 2010

Я бы выбрал Stateless - сервер может генерировать множество экземпляров компонента и обрабатывать входящие запросы параллельно.

Синглтон звучит как потенциальное узкое место - значение @Lock по умолчанию равно @Lock (WRITE), но может быть изменено на @Lock (READ) для компонента или отдельных методов.

3 голосов
/ 31 июля 2014

в соответствии со спецификацией ejb 3.1, стр. 110, глава 4.8.5 «Одиночный параллелизм»:

Разрешено хранить объекты Java EE, которые не поддерживают одновременный доступ (например, менеджеры сущностей, ссылки на сессионный компонент с сохранением состояния) в состоянии экземпляра синглтон-компонента. Однако ответственность за обеспечение доступа к таким объектам не может быть получена более чем одним потоком одновременно.

и, более того, согласно документации Hibernate Entity Entity

EntityManager - это недорогой, не поддерживающий потоки объект, который следует использовать один раз для одного бизнес-процесса, одной единицы работы и затем отбрасывать.

Для меня это означает, что вы никогда не должны внедрять EntityManager в одноэлементный EJB. Я бы использовал одноэлементный EJB в качестве замены для EJB без состояния, только если ВСЕ, что мне нужно реализовать в этом классе, поддерживает параллелизм без необходимости дополнительной блокировки / синхронизации. Поскольку вы или другие программисты рано или поздно можете потерять эту проблему из-за вашего внимания, я лично предпочитаю не использовать одноэлементные EJB-компоненты, за исключением связанных с запуском проблем или функций, которые могут быть реализованы как автономные модули - независимо от других компонентов. В этом смысле кажется нецелесообразным вводить, например, EJB-объекты без состояния в синглтоны. При этом возникает вопрос о моменте времени, когда контейнер фактически выполняет инжекцию SLSB в синглтон? Согласно спецификации EJB 3.1, глава 4.8, внедрение зависимостей выполняется до того, как клиенты получат доступ к экземпляру синглтон-компонента. Таким образом, синглтон, очевидно, будет придерживаться одного и того же экземпляра SLSB, который, по-видимому, неявно становится одноэлементным, но, похоже, нет никаких гарантий для этого. По крайней мере, я не смог ничего найти в спецификациях, поэтому поведение может быть непредсказуемым или, в лучшем случае, специфичным для контейнера, а это не то, что нужно большинству людей.

Таким образом, я бы вводил синглтоны только в синглтоны или синглтоны в SLSB, но не наоборот. В случае внедрения Singleton в Singleton, Spec предлагает вам возможность определить зависимости между синглетонами, чтобы контейнер мог инициализировать их в правильном порядке (см. Спецификацию ejb 3.1, глава 4.8.1 относительно @DependsOn аннотация).

2 голосов
/ 27 июля 2015

@Stateless позволит вам иметь несколько готовых копий для обработки в JVM (насколько позволяет память и размер пула), где @Singleton содержит только одну копию в JVM, даже если одна может поддерживать несколько параллельные потоки, работающие против него.

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

С бином @Stateless доступ более короткий. Кроме того, в случае сбоя он просто возродится и попытается установить новое соединение с ресурсом. Если что-то происходит в одноэлементном режиме, то одноэлементный процесс обрабатывается без необходимости перезапуска приложения, поскольку @PostConstruct вызывается только один раз для JVM.

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

1 голос
/ 03 января 2012

Я думаю, что синглтон при использовании параллелизма не будет работать хуже, чем SLSB Pool, он может быть даже лучше. Единственная проблема - если вы хотите поделиться чем-то между потоками, вам нужно заблокировать это, и это может быть большой проблемой производительности. Таким образом, в этом случае пул SLSB работает намного лучше, поскольку он не на 100% одноэлементный, есть больше экземпляров, один заблокирован, другой подходит. В любом случае, если блокировка на некотором совместном использовании ресурсов всеми SLSB, пул также не поможет.

Короче говоря, я думаю, что синглтон лучше, чем SLSB Pool, вы должны использовать его, если можете. Это также область по умолчанию для Spring Beans.

Я не эксперт по JavaEE, это только мое чувство, пожалуйста, поправьте меня, если я ошибаюсь.

0 голосов
/ 16 июня 2017

Имхо я бы ответил так:

«никакое состояние не должно быть общим для приложения» приводит меня к bean-компоненту без сохранения состояния из-за предложения «Для повышения производительности вы можете выбрать сессионный компонент без сохранения состояния ...».

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

"Никакие задачи при запуске или закрытии не должны выполняться" для меня не имеет значения. Если для правильной настройки bean-компонента необходимо выполнить задачи, они должны быть вызваны методом @PostActivate.

Я бы логично завершил ваш вопрос о том, что использовать @Singleton, поскольку вы запрашивали одновременный доступ. Конечно, вам придется вручную управлять синхронизацией доступа к любым другим ресурсам (которые не являются EJB).

0 голосов
/ 23 июня 2014

вам следует выбрать Singleton, если у вас есть какой-либо ресурс, который будет оставаться постоянным во всем приложении. Как загрузка некоторых данных из какого-либо файла или справочных данных, которые не будут меняться в течение жизненного цикла приложения. в противном случае, перейдите на SLSB. Недостатком SLSB является то, что будет создано несколько объектов, следовательно, будет занято больше памяти.

0 голосов
/ 27 сентября 2013

Если вы уверены, что не делите состояние между потоками, то синглтон будет в порядке, и в этом случае вам также следует пометить класс @ConcurrencyManagement( ConcurrencyManagementType.BEAN ), что позволит одновременно запускать несколько потоков.

0 голосов
/ 05 июля 2013

Я думаю, вам следует использовать сессионный компонент Singleton. Поскольку служба входа в систему должна быть глобальной, и ей не нужно хранить какое-либо состояние для конкретного пользователя или вызова.

...