简体   繁体   English

无状态会话Bean与Singleton会话Bean

[英]Stateless Session Beans vs. Singleton Session Beans

The Java EE 6 Tutorial says: Java EE 6教程说:

To improve performance, you might choose a stateless session bean if it has any of these traits: 要提高性能,您可以选择无状态会话bean,如果它具有以下任何特征:

  • The bean's state has no data for a specific client. bean的状态没有特定客户端的数据。
  • In a single method invocation, the bean performs a generic task for all clients. 在单个方法调用中,bean为所有客户端执行通用任务。 For example, you might use a stateless session bean to send an email that confirms an online order. 例如,您可以使用无状态会话bean发送确认在线订单的电子邮件。
  • The bean implements a web service. bean实现了一个Web服务。

Singleton session beans are appropriate in the following circumstances: 单例会话bean适用于以下情况:

  • State needs to be shared across the application. 状态需要在整个应用程序中共享。
  • A single enterprise bean needs to be accessed by multiple threads concurrently. 单个企业bean需要同时由多个线程访问。
  • The application needs an enterprise bean to perform tasks upon application startup and shutdown. 应用程序需要企业bean在应用程序启动和关闭时执行任务。
  • The bean implements a web service. bean实现了一个Web服务。

But what to use if: 但是如果使用什么:

  • no state has to be shared across the application 不需要在整个应用程序中共享状态
  • a single enterprise bean could be accessed by multiple threads concurrently 单个企业bean可以由多个线程同时访问
  • no tasks on startup or shotdown need to be performed 不需要执行启动或击落任务

Say for example I have a login service with the following interface: 比如说我有一个具有以下界面的登录服务:

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

Should it be annotated with @Singleton or @Stateless? 它应该用@Singleton或@Stateless注释吗? What are the benefits of the one and the other? 这一个和另一个有什么好处? What if LoginService needs to get injected an EntityManager (which would be used concurrently)? 如果LoginService需要注入一个EntityManager(可以同时使用),该怎么办?

Addition: I'm thinking about the Java EE counterpart of Spring service beans, which are stateless singletons. 另外:我正在考虑Spring服务bean的Java EE对应物,它们是无状态单例。 If I understand that correctly the Java EE counterpart are @Stateless session beans and @Singleton Beans are used to configure the application at startup or cleanup at shutdown or to hold application wide objects. 如果我理解正确,Java EE对应的是@Stateless会话bean,并且@Singleton Beans用于在启动时配置应用程序或在关机时清理或保存应用程序范围的对象。 Is this correct? 它是否正确?

I would go for Stateless - the server can generate many instances of the bean and process incoming requests in parallel. 我会选择无状态 - 服务器可以生成bean的许多实例并并行处理传入的请求。

Singleton sounds like a potential bottleneck - the default @Lock value is @Lock(WRITE) but may be changed to @Lock(READ) for the bean or individual methods. Singleton听起来像是一个潜在的瓶颈 - 默认的@Lock值是@Lock(WRITE),但可以更改为@Lock(READ)用于bean或单个方法。

according to the ejb 3.1 spec, page 110, chapter 4.8.5 "Singleton Concurrency": 根据ejb 3.1规范,第110页,第4.8.5节“Singleton Concurrency”:

It is legal to store Java EE objects that do not support concurrent access (eg Entity Managers, Stateful Session Bean references) within Singleton bean instance state. 在Singleton bean实例状态中存储不支持并发访问的Java EE对象(例如,实体管理器,有状态会话Bean引用)是合法的。 However, it is the responsibility of the Bean Developer to ensure such objects are not accessed by more than one thread at a time. 但是,Bean Developer负责确保一次不能通过多个线程访问这些对象。

and furthermore, according to the hibernate entitymanager documentation 此外,根据hibernate entitymanager文档

An EntityManager is an inexpensive, non-threadsafe object that should be used once, for a single business process, a single unit of work, and then discarded. EntityManager是一个廉价的,非线程安全的对象,应该只使用一次,用于单个业务流程,单个工作单元,然后丢弃。

For me, this means, that you should never inject an EntityManager into a singleton EJB. 对我来说,这意味着,您永远不应该将EntityManager注入到单例EJB中。 I would use a singleton EJB as a replacement for a stateless EJB only if EVERYTHING I need to implement in this class supports concurrency without the need to do additional locking / synchronization. 只有在我需要在此类中实现的所有内容支持并发而不需要执行额外的锁定/同步时,我才会使用单独的EJB作为无状态EJB的替代。 As you or other programmers might lose this issue sooner or later from your focus, I personally prefer to not use singleton EJBs except for startup-related issues or features that can be implemented as self-contained units - independently of other beans. 由于您或其他程序员迟早会从您的焦点中丢失此问题,我个人更喜欢不使用单例EJB,除了与启动相关的问题或可以作为自包含单元实现的功能 - 独立于其他bean。 In that sense, it doesn't seem to be advisable to inject for example Stateless EJBs into Singletons. 从这个意义上讲,将无状态EJB注入Singletons似乎并不可取。 Doing so raises the question about the point in time, when the container actually performs the injection of the SLSB into the Singleton? 这样做会引发关于容器实际执行SLSB注入Singleton的时间点的问题? According to the EJB 3.1 Spec, chapter 4.8, the dependency injection gets done before the singleton bean instance can be accessed by clients. 根据EJB 3.1规范,第4.8章,依赖注入在客户端访问单例bean实例之前完成。 So the singleton would obviously stick to the same instance of the SLSB, which seems to become a singleton implicitly, but there doesn't seem to be any guarantee for that. 因此,单身人士显然会坚持SLSB的同一个实例,这似乎是隐含的单身,但似乎没有任何保证。 At least I couldn't find anything in the specs, so the behavior might be unpredictable or in the best case container-specific, which is not what most people will want. 至少我在规范中找不到任何东西,所以行为可能是不可预测的,或者在最好的情况下是容器特定的,这不是大多数人想要的。

Thus, I would only inject Singletons into Singletons or Singletons into SLSBs but not vice versa. 因此,我只会将单身人士注入单身人士或单身人士进入SLSB,但反之则不然。 For the case of an injection of a Singleton into a Singleton, the Spec offers you the opportunity to define the dependencies between the singletons so that the container can initialize them in the correct order (see the ejb 3.1 spec, chapter 4.8.1 concerning the @DependsOn annotation). 对于将Singleton注入Singleton的情况,Spec为您提供了定义单例之间依赖关系的机会,以便容器可以按正确的顺序初始化它们(参见ejb 3.1规范,第4.8.1节关于@DependsOn注释)。

@Stateless will allow you to have multiple copies ready for processing within a JVM (as much as memory and pool size allows) where-as @Singleton there's only one copy in a JVM, even if the single one can support multiple concurrent threads running against it. @Stateless将允许您准备好在JVM中处理多个副本(尽可能多的内存和池大小),其中@Singleton在JVM中只有一个副本,即使单个副本可以支持多个并发线程运行它。

In terms of performance @Singleton would be better, provided that the resources it uses allow long running access. 在性能方面,@ @Singleton会更好,只要它使用的资源允许长时间运行访问。 However, in a distributed environment sometimes bad things occur, eg database or network links may fail. 但是,在分布式环境中,有时会发生不好的事情,例如数据库或网络链接可能会失败。

With a @Stateless bean, the access is more short lived. 使用@Stateless bean,访问权限更短暂。 In addition, should there be a failure it will just respawn and try to establish a new connection to the resource. 此外,如果出现故障,它将重新生成并尝试建立与资源的新连接。 If something happens like that on a singleton, then it's up the the singleton to handle it without requiring an application restart because the @PostConstruct is only called once per JVM. 如果在单例上出现类似的情况,那么单元就可以处理它而不需要重启应用程序,因为@PostConstruct只针对每个JVM调用一次。

I would prefer a bit of fault tolerance vs performance for most situations especially on systems I have no control over. 在大多数情况下,我宁愿选择容错性能,特别是在我无法控制的系统上。

I think Singleton in concurrency usage will not perform worse than SLSB Pool, it might be even better. 我认为Singleton在并发使用方面的性能不会比SLSB Pool差,它可能会更好。 The only problem is if you want to share something between threads, you need lock it, and that could be a big problem of performance. 唯一的问题是如果你想在线程之间共享某些东西,你需要锁定它,这可能是一个很大的性能问题。 So in that case, a SLSB Pool perform much better, because it's not 100% singleton, there are more instances, one got locked, the other one comes up. 因此,在这种情况下,SLSB池执行得更好,因为它不是100%单例,有更多实例,一个被锁定,另一个出现。 Anyway if the lock is on some resource sharing by all SLSBs, the pool won't help neither. 无论如何,如果所有SLSB上的某些资源共享锁定,则该池也不会有任何帮助。

In short, I think singleton is better than SLSB Pool, you should use it if you can. 简而言之,我认为单身人士比SLSB Pool更好,如果可以,你应该使用它。 It's also the default scope for Spring Beans. 它也是Spring Beans的默认范围。

I'm not a JavaEE expert, that's just my feeling, please correct me if I'm wrong. 我不是JavaEE专家,这只是我的感觉,如果我错了,请纠正我。

I think you should use Singleton session bean. 我认为你应该使用Singleton会话bean。 Because a login service should be a global service and it does not need to store any state for a concrete user or invocation. 因为登录服务应该是全局服务,并且不需要为具体用户或调用存储任何状态。

如果您确定不在线程之间共享状态,那么Singleton就可以了,在这种情况下,您还应该使用@ConcurrencyManagement( ConcurrencyManagementType.BEAN )来注释该类,这将允许多个线程同时运行。

you should go for Singleton if you have any resource that is going to remain constant across the application. 如果您有任何资源在整个应用程序中保持不变,那么您应该选择Singleton。 Like loading some data from some file or reference data which would not change across the application lifecycle. 就像加载某些文件或参考数据中的一些数据一样,这些数据在整个应用程序生命周 otherwise, go for SLSB. 否则,去SLSB。 The drawback of SLSB is that multiple objects would be created hence more memory would be occupied. SLSB的缺点是会创建多个对象,因此会占用更多内存。

Imho I would answer like that: Imho我会这样回答:

"no state has to be shared across the application" leads me to stateless bean because of the sentence "To improve performance, you might choose a stateless session bean...". “在整个应用程序中不需要共享状态”会导致我使用无状态bean,因为句子“为了提高性能,你可以选择无状态会话bean ......”。

Considering "a single enterprise bean could be accessed by multiple threads concurrently" you would have to use singleton. 考虑到“单个企业bean可以由多个线程同时访问”,您将不得不使用单例。 If I got it right it is not even possible to access a stateless bean's concurrently when properly used. 如果我做对了,在正确使用时甚至不可能同时访问无状态bean。

"no tasks on startup or shotdown need to be performed" would not matter to me. “在启动或击落时不需要执行任务”对我来说无关紧要。 If tasks have to be done to properly setup a bean then they have to be invoked by a @PostActivate method. 如果必须完成任务以正确设置bean,则必须通过@PostActivate方法调用它们。

I would logically conclude your question what to use to @Singleton since you asked for concurrent access. 我会在逻辑上总结你的问题,因为你要求并发访问,所以要对@Singleton使用什么。 Of course you will have to manually control snychronisation of accesses on any further resources (which are not EJBs). 当然,您必须手动控制对任何其他资源(不是EJB)的访问的同步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM