用于异步日志记录的多线程与JMS队列

时间:2015-04-28 03:27:00

标签: java multithreading performance logging asynchronous

要求:记录页面视图和表单提交等事件。每页有~1秒SLA。该应用程序一次可以拥有100个并发用户。

日志事件存储在数据库中。

解决方案:我最初的想法是使用异步日志记录方法,其中控件返回到应用程序,并且日志记录发生在另一个线程中(通过Spring的线程池任务执行程序)。

然而有人建议使用JMS将是一种更强大的方法。使用此方法时,是否需要添加的工作(设置队列,写入队列,从队列中读取)?

在实施此类内容时,(生产环境中)需要注意哪些最佳做法/事项?

3 个答案:

答案 0 :(得分:1)

使用JMS进行日志记录是完全不匹配的。 JMS是MQ系列等中间件工具的Java抽象。这是完全矫枉过正的,会让你经历一个设置和配置地狱。 JMS还允许您在事务上下文中放置消息,因此您已经快速了解JMS可能不如@rjsang所建议的数据库写入更好。

这不是JMS不是一个很好的技术。它是一种很好的技术,可以正确应用。

对于同步日志记录,您最好只依赖于直接支持它的日志API,如Log4j2。在您的情况下,您可能希望使用AsyncAppender配置JDBCAppender。 Log4j2有更多的appender作为附加选项,包括一个用于JMS。但是,至少使用Logging抽象,您可以将其全部配置为可以在以后改变主意。

将来我们可能会遇到与Asynchronous CDI Events类似的东西,它应该与JMS类似,但会更轻量级。也许你可以通过将CDI事件与EJB异步方法相结合来获得类似的工作。只要您不将EJB与远程接口一起使用,它也应该非常轻量级。

答案 1 :(得分:1)

这两种方法都有效,但如果您的应用意外停止,则一种方法很容易受到攻击。在第一个场景中,尚未写入数据库的事件将丢失。使用持久性JMS队列意味着将从队列中读取这些事件并在重新启动时持久保存到数据库。

当然,如果您的数据库写入比将类似大小的消息放到JMS队列上要慢得多,那么您可能正在解决错误的问题?

答案 2 :(得分:0)

如果您愿意,可以尝试使用完全异步和外部工具。如果您必须以任何价格坚持使用SLA并且弹性对您很重要,您可以尝试使用logstash或离线处理日志。通过这样做,您可以将应用程序与数据库分离,并且不再依赖于数据库性能。如果数据库速度很慢并且您正在使用异步记录器,则队列可能会运行完毕。

使用GELF的logstash,整个日志处理在不同的(甚至是远程的)JVM中处理。离线处理(例如,您编写CSV日志)允许您将日志数据加载到数据库中。