我的目标是创建Java EE Web服务,该服务将同时接受数千个(或将来更多)的请求,并且必须以列表或类似结构存储来自请求的数据。我想将来自请求的对象存储在内存中,但这不是强制性的。将从每个请求中提取一些对象并添加到选定的数据结构中。Web 服务将有两个操作:添加到结构和从结构中删除。删除请求将包含对象实例变量的值。可能是唯一的 ID 或其他一个或多个实例变量。将始终有一个对象要删除(如果请求无效,则为 0)。将删除具有相等实例变量值的对象。
我的想法是使用两个EJB。首先是@Stateless并作为 Web 服务公开。它将从请求中提取对象并调用第二个 EJB 以在数据结构中添加或删除请求的对象。第二个 EJB 将@Singleton,并且具有从请求中提取对象的实例变量 ArrayList<>。正如我所说,它根本不必须是 ArrayList 或 List。
我也考虑过使用一个 EJB,它必须@WebService @Singleton,但文档说这种组合是"可能的,但是......此规范未定义。
Arjan,你的要求并不完全清楚。假设您正在构建一个每秒 1000 个请求>高负载应用程序,我会这样做:
Servlet-processing
- 将"对象"数据容器分隔到每个用户的 HTTP 会话中(如果 HTTP 会话可用)
- 将同步列表添加到您的 HTTP 会话中,并在每个请求上对同步的私有列表进行操作,并将 Web 客户端详细信息添加到此 HTTP 会话存储列表中
- 将 httpsession 列表的引用添加到下一个提到的 SingletonEJB
单例 EJB
- 创建单一实例 EJB 为提取/
- 过滤/处理的对象添加列表字段 您的对象类型 类型
- 为基于 HTTP 会话且未过滤但同步的列表的引用添加第二个集合
TimerEJB
- 创建一个定时器 EJB 以定期运行,例如每秒运行一次
- 此函数将遍历 refCol 中所有引用的列表,并提取和过滤所需的对象,并确保清理基于 HTTP 会话的列表。
该解决方案的优势:
- 将用户的 MEM 负载推送到他们的会话
- 不要在非常高的负载下遇到同步/互斥锁问题,因为您的 timerEJB 在单例 Bean 中的中央和过滤列表上的操作时间很短。 只要
- 您的会话保持较小,您就可以扩展
- 用于筛选的 CPU 密集型解决方案和用于保留筛选对象的 IO 密集型解决方案位于客户端请求之外,客户端不会遇到性能问题。
- 定时器时间表可根据您的需要更改
缺点:
- 复杂度稍高
- 您必须清理 refColl 中对已关闭 http 会话列表的引用。通过在复合类中或通过任何其他自定义解决方案提供会话和对会话列表的引用。如果不清理,您的堆将通过保留对已"已杀死"的 http 会话列表的引用而变得臃肿。
不能在 WS 上使用 @Singleton,因为容器可能会启动多个实例来处理繁重的请求负载。
您的@Singleton Bean 不能使用 ArrayList<>因为会有并发访问。您应该改用 ConcurrentLinkedQueue。如何识别删除操作的请求?也许ConcurrentHashMap会更好。
如果你想拥有"数千(或将来更多)",你迟早会耗尽内存,除非你将请求转储到数据库或文件中。带有JPA的数据库将是最简单的,您只需在WS和Request对象上进行少量注释即可实现它。