2013-06-29 91 views
0

我有一个运行在Tomcat 7上的Spring 3.0 WebMVC应用程序。在应用程序启动时,我启动后台线程以从数据库加载内存缓存。该线程通常需要花费一个多小时才能从数据库加载所有数据。在同一个应用程序中,我有一个@Controller注释类,它公开了一个REST接口,通过这个接口,客户端可以从加载的缓存中获取对象。长时间运行的后台线程导致HTTP请求超时

我们的一个要求是,在数据加载完成之前完成的任何REST请求都会立即返回一个SERVICE_UNAVAILABLE(503)HTTP代码给客户端。为了做到这一点,我设置了一个布尔标志的简单检查,即在执行任何工作之前,控制器中的每个请求方法都会进行检查。如果该值为false,则该方法应该立即以503代码返回。加载器线程在完成加载后将该标志设置为true,以允许请求方法正常工作。

问题是后台线程似乎导致发送到我的控制器的所有HTTP请求在30秒后超时而不是立即触发标记并立即向客户端返回503代码。我不是Tomcat线程问题的专家,我不知道在创建我的长时间运行的后台线程时是否做错了什么?我基本上使用“implements Runnable”方法创建线程,如this问题中所述,并在包含bean初始化时启动线程。有没有更好的方法来启动Tomcat中长时间运行的后台线程,而不会干扰请求处理?还是还有别的东西我失踪了?

+0

你如何同步访问布尔标志? –

+0

@DavidSchwartz该标志是请求方法通过缓存DAO对象检查的内存缓存中的值。加载器线程在通过相同的高速缓存DAO对象完成时简单地更新此缓存值,我相信这是线程安全的(不是100%确定);它不会在加载完成之前访问它,所以我不认为这是一个问题? – Tom

+0

而不是污染每一项服务,只是实现一个过滤器会不会更容易和更好维护?当然,这并不能解决您所问的问题,但可能会将问题简化为单一交互场所。 –

回答

0

如果我是你,我会做不同的几件事情:

  1. 见,如果你想使用一个外部高速缓存。在过去,我使用Project Voldemort(http://www.project-voldemort.com/voldemort/)取得了一些成功,还有其他的选择。
  2. 如果您将缓存外部化,那么重新启动Tomcat将不需要重新加载缓存。
  3. 构建一个单独的应用程序,其任务是加载缓存。
  4. 如果您想要处理请求,如果您正在查找的条目在缓存中不可用,请直接从数据库中查找。
  5. 请勿在Tomcat等应用程序容器中使用自己的线程。 Tomcat内置了自己的线程管理逻辑,创建用户线程是一个BIG-NO。
+0

我很好奇,如果你有一个参考文件来备份你在#5中的声明...那个用户线程不是一个在Tomcat中运行的web应用程序内创建的好主意吗? – Tom

+0

我记得我读过罗德约翰逊的书,不幸的是我无法追查它。另外,我在实际上已经看到我们的项目中线程作为请求处理的一部分开始,导致系统停止生产。我发现这个链接在这个主题讨论的地方:http://stackoverflow.com/questions/533783/why-spawning-threads-in-java-ee-container-is-discouraged –