2009-11-25 121 views
5

我有基于Java servlet的Web应用程序。我想以异步方式实现一些操作,例如写入日志。在Java Web应用程序中执行异步操作的最简单方法

我想避免JMS开销并做一些简单的事情。

在服务器环境中,我自己管理线程似乎不是一个好主意,您可能需要使用服务器线程池等。 简单异步操作的最佳选择是什么?

编辑:

只是为了澄清,因为许多使用log4j的或其他的日志库,写日志操作上建议在这里更多的例子。我感兴趣的是如何异步执行任何不需要顺序执行的操作。想法是立即回复用户,并在另一个线程中继续处理昂贵的操作。

关于日志问题,我们有一个审计日志,我们实现了将大量数据写入数据库,并在审计操作和帮助台期间由用户使用。向DB写入大量信息可能会非常昂贵。我们使用log4j作为系统日志,由于appender是文件appender,因此我们的系统日志没有性能问题。

+0

那么......你需要保证异步操作的执行,或者如果它可能不会被执行,如果 - 例如 - 服务器重新启动? JMS的复杂性大部分源于在这种情况下提供恢复。 – meriton 2009-11-25 23:06:01

+0

好问题。我想它不需要比现在更“保证”,同时进行。例如,如果我的审计日志的数据库由于某种原因不可用,则会导致系统日志中记录该错误。服务器关闭是有趣的角落情景我想在这种情况下,我可以对用户说:切断流量,然后等到队列中没有消息后再关闭服务器。一个显示消息数量的简单servlet可以做.. – Dan 2009-11-25 23:31:23

回答

1

正如很多人在这里所说的,日志并不适合异步。不过,我认为你有充分的理由相信。

在这种情况下,我会使用Queue(例如ConcurrentLinkedQueue)和一个低优先级的线程(从应用程序启动时启动并关闭时,例如从启动时运行的servlet启动) 。线程应该从队列中选择消息,并做它的事情。线程应该通过notify()方法或等间隔来唤醒。

风险:队列在重负载下可能无法控制地增长(因为线程可能得不到足够的CPU周期)。

还有其他方法可以触发异步操作(例如Timer,Future,...),但我认为它们不适合快速小型操作。

+1

另一个原因是通过推迟记录活动来减少用户可见的操作时间。在这种情况下,您再次将日志消息放入队列,将页面返回给用户,然后将日志队列刷入介质(磁盘,数据库,网络记录器)。总吞吐量不高,但用户体验更好。 – 2009-11-25 18:28:13

0

如果你想要做的只是简单的记录,那么Log4j是简单易用的。

+0

不要以为log4j是异步的,除非你使用JMS或自定义appender :-) – Karl 2009-11-25 17:19:30

+2

http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j /AsyncAppender.html – ChadNC 2009-11-25 17:23:05

0

如果您只是试图以异步方式写入日志,我会完全避免它,只是在适当的情况下使用缓冲输出。

我从来没有使用它自己,但从Apache的http://mina.apache.org/项目有很好的评论,但我认为这主要是在网络层面。

0

你想让更重的操作异步,而不是非常轻量级的操作,如日志记录。一旦你形成日志消息,它的实际写入应该非常快(毕竟,你的磁盘控制器也会缓存)。

所以,如果你有一个沉重的操作会让你的web应用程序停滞并使其响应速度变慢,那么使用像JMS这样的持久消息队列方法通常是一个好主意。

如果你想做日志记录,我建议SLF4J,这是Log4J的后继者,非常强大和高效。

如果您正在考虑登录多机环境,一种方法是配置您的记录器以将消息写入多播组,从中读取这些消息并将它们写入磁盘中的一个或多个日志聚合服务器。

相关问题