在Spring Data MongoDB中处理读取超时的最佳方法

时间:2015-01-07 22:33:16

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

所以我们不时会看到这样的例外情况:

java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:150)
at java.net.SocketInputStream.read(SocketInputStream.java:121)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at org.bson.io.Bits.readFully(Bits.java:48)
at org.bson.io.Bits.readFully(Bits.java:35)
at org.bson.io.Bits.readFully(Bits.java:30)
at com.mongodb.Response.<init>(Response.java:42)
at com.mongodb.DBPort$1.execute(DBPort.java:141)
at com.mongodb.DBPort$1.execute(DBPort.java:135)
at com.mongodb.DBPort.doOperation(DBPort.java:164)
at com.mongodb.DBPort.call(DBPort.java:135)
at com.mongodb.DBTCPConnector.innerCall(DBTCPConnector.java:292)
at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:271)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:84)
at com.mongodb.DBCollectionImpl.find(DBCollectionImpl.java:66)
at com.mongodb.DBCollection.findOne(DBCollection.java:870)
at com.mongodb.DBCollection.findOne(DBCollection.java:844)
at com.mongodb.DBCollection.findOne(DBCollection.java:790)
at org.springframework.data.mongodb.core.MongoTemplate$FindOneCallback.doInCollection(MongoTemplate.java:2000)

在代码中处理和恢复这些内容的最佳方法是什么? 我们是否需要围绕每个mongodb电话进行“重试”?

5 个答案:

答案 0 :(得分:5)

您可以使用MongoClientOptions对象设置不同的可选连接参数。您正在设置心跳频率以确保驱动程序重试连接。同时设置套接字超时以确保它不会持续太长时间。

  1. MinHeartbeatFrequency:如果驱动程序必须经常重新检查服务器的可用性,它将至少在上一次检查后等待很长时间,以避免浪费精力。默认值为10毫秒。
  2. HeartbeatSocketTimeout:心跳检定超时
  3. SocketTimeout:超时连接
  4. Reference API

    为避免过多的代码重复,您可以选择遵循下面给出的某种模式。 基本思想是避免在项目中到处乱丢任何与数据库连接相关的配置。

    /**
     * This class is an abstraction for all mongo connection config
     **/
     @Component
     public class MongoConnection{
    
        MongoClient mongoClient = null;
    
        ...
    
       @PostConstruct
       public void init() throws Exception {
                // Please watch out for deprecated methods in new version of driver.
                mongoClient = new MongoClient(new ServerAddress(url, port), 
                                MongoClientOptions.builder()
                                .socketTimeout(3000)
                                .minHeartbeatFrequency(25)
                                .heartbeatSocketTimeout(3000)
                                .build());
                mongoDb = mongoClient.getDB(db);
            .....   
       }
    
       public DBCollection getCollection(String name) {
            return mongoDb.getCollection(name);
        }
       }
    

    现在您可以在DAO-s中使用MongoConnection

    @Repository
    public class ExampleDao{
    
      @Autowired
      MongoConnection mongoConnection;
    
      public void insert(BasicDBObject document) {
         mongoConnection.getCollection("example").insert(document);
      }  
    }
    

    您还可以在MongoConnection中实现所有数据库操作,以全面介绍一些常用功能。例如,为所有&#34;插入&#34;

    添加日志记录

答案 1 :(得分:0)

处理重试的众多选项之一是Spring重试项目

https://github.com/spring-projects/spring-retry

它为Spring应用程序提供声明性重试支持。 这基本上就是这个问题的Spring答案。它用于Spring Batch,Spring Integration,Spring for Apache Hadoop(等等)。

答案 2 :(得分:0)

如果您想要处理MongoDB以及任何其他外部参考的超时(和相关)问题,那么您应该尝试使用Netflix的Hystrix(https://github.com/Netflix/Hystrix)。

这是一个很棒的库,可以很好地与RX和异步处理集成,最近变得非常流行。

答案 3 :(得分:0)

如果我没有弄错的话,我认为当你尝试建立连接或者只是在连接池中做好准备时,你需要像超时那样配置你的属性。 或者,您可以只检查您的网络或计算机,并将请求数据拆分更多次以减少网络传输时间

答案 4 :(得分:0)

https://github.com/Netflix/Hystrix是处理依赖项的工具。