我目前正在将EJB项目从2.0版升级到3.2版(所有有状态)。业务逻辑保持不变,唯一改变的是EJB部分(用注释替换描述符文件,使用注入点而不是传统查找等)。 从请求处理的角度来看,一切似乎都运行良好,问题在于性能。 使用一个连接的客户端,每个请求大约需要300毫秒。如果我添加第二个客户端,平均时间会跳到700毫秒。对于第三个客户端,平均值超过1秒,依此类推。使用EJB 2.0版本,处理时间略有增加(50~100ms),即使有更多客户端,也无需担心。
退化非常明显,我无法弄清楚原因。
我已经玩过EJB超时,事务类型等,但没有运气。我也尝试过分析服务器(通过JMC),但找不到任何可疑的东西。
好像所有请求都是按顺序处理,而不是同时处理。
有人可以提供一些可能原因的提示吗?我有什么配置吗?
注意: WebSphere 9和GlassFish 4.1.1都出现了问题,因此它显然是应用程序的问题。
编辑#1
检查应用程序的日志后,我可以确认请求是按顺序处理的,不是并发处理。
按照迈克尔的建议,我查看了一个线程转储,并且在给定的时刻,我有:
没有线程受阻的迹象。
有什么想法吗?
答案 0 :(得分:1)
你是如何测试的?
这听起来像多个客户端正在获得相同的有状态会话bean实例。
容器将序列化对同一SFSB实例的调用。它应该这样做,如果它之前没有发生,那么你可能有一些平台相关的部署描述符禁用了这种行为。
但是,如果您正在使用测试框架并且所有客户端都在进行相同的会话,那么这也会使您看起来遇到问题。
§4.3.13EJB规范的“序列化会话Bean方法”说:
容器序列化对每个有状态和无状态会话的调用 bean实例。大多数容器都支持a的许多实例 会话bean并发执行;但是,每个实例只能看到 方法调用的序列化序列。因此,有状态或 无状态会话bean不必编码为可重入。
如果您在所有客户端之间共享单个SFSB实例,则可能适合将其从@Stateful更改为@Singleton。 Singleton EJB通过@ConcurrencyManagement和@Lock注释提供明确的重入控制。如果您对EJB的线程安全性完全满意,那么您可以通过以下方式标记您的bean:
@Singleton
@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
public class MyStatefulSessionBeanMasqueradingAsASingleton {
...
}