MongoCleaner线程在Spring Data应用程序上累积

时间:2013-10-16 12:08:52

标签: java multithreading spring mongodb spring-data-mongodb

我有一个使用Spring Data的java网站提供与MongoDB的集成。 应用程序运行良好,但不断累积线程,直到服务器最终出现此错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongo': Invocation of init method failed; nested exception is java.lang.OutOfMemoryError: unable to create new native thread
2013-10-15T14:51:40.305986+00:00 app[web.1]: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongo': Invocation of init method failed; nested exception is java.lang.OutOfMemoryError: unable to create new native thread
2013-10-15T14:51:40.305986+00:00 app[web.1]: 1343234 [http-nio-55996-exec-6] DEBUG org.springframework.web.servlet.DispatcherServlet  - Could not complete request
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1455)
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at org.springframework.contex
t.support.GenericXmlApplicationContext.<init>(GenericXmlApplicationContext.java:71)
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
2013-10-15T14:51:40.305986+00:00 app[web.1]:    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:591)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at com.jux.model.Signin.persistSignin(Signin.java:40)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at com.intuit.controller.LoginController.authenticateUser(LoginController.java:71)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at java.lang.reflect.Method.invoke(Method.java:616)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.springframework.web.servlet.FrameworkServlet.
processRequest(FrameworkServlet.java:882)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
2013-10-15T14:51:40.306169+00:00 app[web.1]:    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
2013-10-15T14:51:40.306727+00:00 app[web.1]:    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
2013-10-15T14:51:40.306727+00:00 app[web.1]:    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
2013-10-15T14:51:40.306727+00:00 app[web.1]:    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
2013-10-15T14:51:40.306334+00:00 app[web.1]:    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
2013-10-15T14:51:40.306727+00:00 app[web.1]:    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
2013-10-15T14:51:40.306875+00:00 app[web.1]:    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
2013-10-15T14:51:40.306875+00:00 app[web.1]: Caused by: java.lang.OutOfMemoryError: unable to create new native thread
2013-10-15T14:51:40.306875+00:00 app[web.1]:    at java.lang.Thread.start0(Native Method)
2013-10-15T14:51:40.306727+00:00 app[web.1]:    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
2013-10-15T14:51:40.306727+00:00 app[web.1]:    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
2013-10-15T14:51:40.306875+00:00 app[web.1]:    at com.mongodb.Mongo.<init>(Mongo.java:192)
2013-10-15T14:51:40.306875+00:00 app[web.1]:    at java.lang.Thread.start(Thread.java:657)

我试图更新我正在使用的Spring Data版本,并尝试使用1.3.1.RELEASE和1.3.2.BUILD-SNAPSHOT - 同样的问题。

我还读过Mongo驱动程序应该关闭这些线程,我不需要在关闭线程上完成任何工作,但我开始怀疑。 知道如何解决这个问题吗?

这是我的mongodb.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:context="http://www.springframework.org/schema/context"
          xmlns:mongo="http://www.springframework.org/schema/data/mongo"
          xsi:schemaLocation=
          "http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.0.xsd
          http://www.springframework.org/schema/data/mongo
          http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
          http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- Default bean name is 'mongo' -->
    <mongo:mongo host="xxxxxx.mongolab.com" port="12345">
        <mongo:options connections-per-host="8"
                   threads-allowed-to-block-for-connection-multiplier="4"
                   connect-timeout="1000"
                   max-wait-time="1500"
                   auto-connect-retry="true"
                   socket-keep-alive="true"
                   socket-timeout="1500"
                   slave-ok="true"
                   write-number="1"
                   write-timeout="0"
                   write-fsync="true"/>
    </mongo:mongo>
    <mongo:db-factory id="myMongoDbFactory"
                  host="xxxxx.mongolab.com"
                  port="12345"
                  dbname="zzzz"
                  username="yyyy"
                  password="xxxx"/>

    <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
        <constructor-arg ref="myMongoDbFactory"/>
    </bean>

</beans>

这是我在控制器中对MongoDB进行查询的方式:

@RequestMapping(value = "/deletePart.htm", method = RequestMethod.GET)
public String deletePart(String part_id) {
    LOG.debug("in deletePart, part_id: "+part_id);
    ApplicationContext ctx = new GenericXmlApplicationContext("mongodb.xml");
    MongoOperations mongoOps = (MongoOperations)ctx.getBean("mongoTemplate");
    Part p = mongoOps.findOne(new Query(where("id").is(part_id)), Part.class);
    mongoOps.remove(p);     
    return "redirect:/parts.htm";
}

以下是线程如何累积并永不关闭的图片: Threads accumulating:

并从线程转储中,这是一个挂起线程的详细信息:

"MongoCleaner1448498515" daemon prio=5 tid=0x00007f939f888000 nid=0x12f03 waiting on condition [0x00000001ac920000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
    at java.lang.Thread.sleep(Native Method)
    at com.mongodb.Mongo$CursorCleanerThread.run(Mongo.java:770)

   Locked ownable synchronizers:
    - None

2 个答案:

答案 0 :(得分:1)

我不确定这是否是原因,但您绝对不应为每个请求创建新的上下文。

将mongodb.xml添加到根应用程序上下文中。

答案 1 :(得分:1)

如果关闭应用程序上下文,将关闭Mongo实例并阻止无限制的线程增长:

@RequestMapping(value = "/deletePart.htm", method = RequestMethod.GET)
public String deletePart(String part_id) {
   LOG.debug("in deletePart, part_id: "+part_id);
   GenericXmlApplicationContext ctx = new GenericXmlApplicationContext("mongodb.xml");
   try {
      MongoOperations mongoOps = (MongoOperations)ctx.getBean("mongoTemplate");
      Part p = mongoOps.findOne(new Query(where("id").is(part_id)), Part.class);
      mongoOps.remove(p);     
      return "redirect:/parts.htm";
   } finally {
      ctx.close();   // close the context, will close the Mongo instance
   }
}

但即使这样可行,您的应用程序仍然不应该为每个请求创建一个应用程序上下文实例。