我有一个通过 HTTP 接口接收消息的 Web 应用程序,例如:
http://server/application?source=123&destination=234&text=hello
该请求包含发件人的 ID、收件人的 ID 和消息的文本。
此消息应按如下方式处理:
- 从数据库中查找源和目标的匹配用户对象
- 创建对象树:包含消息文本字段的 Message 和用于源和目标的两个 User 对象
- 将此树持久化到数据库中。
树将由我无法触及的其他应用程序加载。
我使用 Oracle 作为后备数据库,使用 JPA 和 Toplink 进行数据库处理任务。如果可能的话,我会留在这些地方。
如果没有太多优化,我可以在我的环境中实现约 30 个请求/秒的吞吐量。这并不多,我需要约 300 个请求/秒。所以我测量了性能瓶颈在哪里,发现调用em.persist()
占用了大部分时间。如果我简单地注释掉该行,吞吐量将远远超过 1000 个请求/秒。
我尝试编写一个小型测试应用程序,它使用简单的 JDBC 调用将 100 万条消息持久保存到同一个数据库。我使用了批处理,这意味着我做了 100 次插入然后提交,并重复直到所有记录都在数据库中。在这种情况下,我测量了大约 500 个请求/秒的吞吐量,这可以满足我的需求。
很明显,我需要在这里优化插入性能。然而,正如我之前提到的,我想继续使用 JPA 和 Toplink,而不是纯粹的 JDBC。
你知道用 JPA 和 Toplink 创建批量插入的方法吗?您能否推荐任何其他技术来提高 JPA 持久性性能?
附加信息:
“请求/秒”在这里表示:请求总数/从测试开始到最后一条记录写入数据库的总时间。
我试图em.persist()
通过在 servlet 内容和持久化程序之间创建一个内存队列来进行异步调用。对演出有很大帮助。然而,队列确实增长得非常快,因为应用程序将连续接收约 200 个请求/秒,这对我来说不是一个可接受的解决方案。
在这种分离的方法中,我收集了 100 毫秒的请求,并em.persist()
在提交事务之前调用了所有收集的项目。EntityManagerFactory 在每个事务之间缓存。