Spring 数据 mongodb 未关闭 mongodb 连接

Spring data mongodb not closing mongodb connections

我正在为我的 Web 应用程序使用 spring-data-mongodb (1.7.0.RELEASE) 和 spring-webmvc 框架。我正在使用 mongoRepository 使用基本的 CRUD 函数,但我没有关闭代码中的 mongo 连接,因为我认为 spring-data-mongodb 会自行关闭它, 但它一直在打开新连接而不是关闭它们。这些太多的连接会导致我的应用程序崩溃,我必须一次又一次(每天两次)重新启动 tomcat 来克服这个问题。

注意:Spring 应用程序和 mongod 在同一台服务器上。 这是崩溃后的日志 -

    2015-07-17T01:31:20.068-0400 I NETWORK  [conn3645] end connection 127.0.0.1:55302 (2583 connections now open)
    2015-07-17T01:31:20.071-0400 I NETWORK  [conn1713] end connection 127.0.0.1:48174 (2352 connections now open)
    2015-07-17T01:31:20.072-0400 I NETWORK  [conn2250] end connection 127.0.0.1:51017 (2325 connections now open)
    2015-07-17T01:31:20.072-0400 I NETWORK  [conn2149] end connection 127.0.0.1:50670 (2320 connections now open)

这是重启后的日志tomcat

2015-07-17T01:31:29.994-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:53599 #3984 (1 connection now open)
2015-07-17T01:31:33.263-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:53740 #3985 (2 connections now open)
2015-07-17T01:31:33.580-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:53750 #3986 (3 connections now open)
2015-07-17T02:10:06.477-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:50086 #3987 (4 connections now open)
2015-07-17T02:10:06.590-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:50090 #3988 (5 connections now open)
2015-07-17T02:10:11.682-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:50242 #3989 (6 connections now open)
2015-07-17T02:10:11.780-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:50244 #3990 (7 connections now open)
2015-07-17T02:10:12.545-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:50255 #3991 (8 connections now open)
2015-07-17T02:10:12.605-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:50258 #3992 (9 connections now open)
2015-07-17T02:10:13.413-0400 I NETWORK  [initandlisten] connection accepted from 127.0.0.1:50299 #3993 (10 connections now open)

每当我向应用程序发送请求时它都会增加。

这是崩溃后的 tomcat 日志 -

Jul 16, 2015 3:59:57 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run
SEVERE: Socket accept failed
java.net.SocketException: Too many open files
    at java.net.PlainSocketImpl.socketAccept(Native Method)
    at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:404)
    at java.net.ServerSocket.implAccept(ServerSocket.java:545)
    at java.net.ServerSocket.accept(ServerSocket.java:513)
    at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:60)
    at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:222)
    at java.lang.Thread.null(Unknown Source)

它是一个开发服务器,它的流量每分钟少于 10 个调用。

有人请建议我应该如何关闭这些连接?

Spring 不会自动关闭连接。只有当上下文关闭时,它才会关闭连接。

看看this article

您最好按照article

配置mongo选项

但是您必须根据您的应用程序流量微调这些值。

<beans>

  <mongo:mongo host="localhost" port="27017">
    <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/>

</beans>

Spring-data-mongodb使用连接池重用连接,所以不会关闭连接,下次重用。为此,您需要创建 mongo class.

的单例实例

如果您使用 Spring IOC(使用@AutoWired)创建 Mono-repository 实例,它工作正常因为它 returns 单例实例,所以一次只有几个连接。但是我没有使用 @Autowired 创建存储库实例,我是通过新方法手动创建它们,所以它每次都给我新的 mongo() 实例。 new mongo instance 表示与数据库的新连接。而且没有办法关闭它。这就是为什么我有太多打开的连接。

MongoClient 维护一个连接池,您使用 MongoClient 打开一次 Db 连接并在您的应用程序中重用它,因为设置新的 TCP 连接在时间和内存方面都是昂贵的,这就是您重用连接的原因。此外,新连接也会导致在 MongoDB 上使用 Db 上的内存创建新线程。

  • 需要注意的一点是 connectToMongo 方法中存在竞争条件。您需要同步对该方法的访问以确保最多创建一个 MongoClient 实例。

我也遇到过同样的问题,因为使用的是 new 而不是自动装配,如果您手动这样做,请使用

关闭连接
 mongoDBObject.getDB().getMongo().close().