简体   繁体   English

使用 java 使用 Mongo 连接池接收消息时超时

[英]Timeout while receiving message with Mongo Connection pooling using java

In production we are connecting with a MongoDB using Java (connection pooling).在生产中,我们使用 Java(连接池)与 MongoDB 连接。 Every day we are getting almost 500 requests with the error below (MongoSocketReadTimeoutException) and we are not using any complex query.每天我们都会收到近 500 个带有以下错误的请求 (MongoSocketReadTimeoutException),而且我们没有使用任何复杂的查询。 Could it be stale Mongo connections?可能是陈旧的 Mongo 连接吗?

I didn't see a problem with our code or MongoDB slowness.我没有发现我们的代码或 MongoDB 缓慢的问题。 Please review my code below and suggest if any parameters need to be added or anything needs to be changed.请查看下面我的代码,并建议是否需要添加任何参数或需要更改任何内容。

    at 2018-03-07 19:52:43 ERROR ::Error while connecting the Mongo DB {}
com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message
        at com.mongodb.connection.InternalStreamConnection.translateReadException(InternalStreamConnection.java:474)
        at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:225)
        at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.java:102)
        at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.java:435)
        at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.java:112)
        at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159)
        at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:286)
        at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.java:173)
        at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:215)
        at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:206)
        at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:112)
        at com.mongodb.operation.FindOperation$1.call(FindOperation.java:487)
        at com.mongodb.operation.FindOperation$1.call(FindOperation.java:482)
        at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:239)
        at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:212)
        at com.mongodb.operation.FindOperation.execute(FindOperation.java:482)
        at com.mongodb.operation.FindOperation.execute(FindOperation.java:79)
        at com.mongodb.Mongo.execute(Mongo.java:772)
        at com.mongodb.Mongo$2.execute(Mongo.java:759)
        at com.mongodb.FindIterableImpl$FindOperationIterable.first(FindIterableImpl.java:207)
        at com.mongodb.FindIterableImpl.first(FindIterableImpl.java:148)
        at com.tecnotree.bom.validation.dao.MongoManager.getJsonObject(MongoManager.java:88)
        at com.tecnotree.bom.validation.dao.CustomerMasterDao.getService(CustomerMasterDao.java:48)
        at com.tecnotree.bom.validation.service.ValidationService.processValidation(ValidationService.java:214)
        at com.tecnotree.bom.validation.service.ValidationService.processRequest(ValidationService.java:125)
        at sun.reflect.GeneratedMethodAccessor185.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
        at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvid
er.java:205)

Code代码

public class ConnectionManager {
    private ConnectionManager() {

    }
    private static final Logger logger = LoggerFactory.getLogger(ConnectionManager.class);
    private static MongoClient mongoClient = null;


    private static String connections = null;
    private static String connectionTimeOut = null;
    private static String socketTimeOut = null;
    private static String serverSelectionTimeOut = null;
    private static String URL = null;
    private static String username = null;
    private static String password = null;
    private static String hostname = null;
    private static String port = null;
    private static String maxConnectionIdleTime = null;
    private static String minConnectionsPerHost = null;
    private static String maxConnectionLifeTime = null;



    private static String dbName = null;

    static {
        dbName = ValidationProperties.getValue("clm.db.dbName");
        mongoClient = getCLMSecondaryMongoConnection();


    }

    private static MongoClient getCLMSecondaryMongoConnection() {

        connections = ValidationProperties.getValue("clm.db.connectionsPerHost");
        connectionTimeOut = ValidationProperties.getValue("clm.db.connectTimeoutMS");
        socketTimeOut = ValidationProperties.getValue("clm.db.socketTimeOut");
        serverSelectionTimeOut = ValidationProperties.getValue("clm.db.serverSelectionTimeOut");
        username = ValidationProperties.getValue("clm.db.userName");
        password = ValidationProperties.getValue("clm.db.password");
        hostname = ValidationProperties.getValue("clm.db.hostname");
        port = ValidationProperties.getValue("clm.db.portnumber");
        maxConnectionIdleTime = ValidationProperties.getValue("clm.db.maxConnectionIdleTime");
        minConnectionsPerHost = ValidationProperties.getValue("clm.db.minConnectionsPerHost");

        try {
            List<MongoCredential> creds = new ArrayList<MongoCredential>();
            creds.add(MongoCredential.createCredential(username, dbName, password.toCharArray()));
            /*creds.add(MongoCredential.createMongoCRCredential(username, dbName, password.toCharArray()));*/
            MongoClientOptions.Builder optionsBuilder = MongoClientOptions.builder();
            optionsBuilder.connectTimeout(Integer.parseInt(connectionTimeOut));
            optionsBuilder.serverSelectionTimeout(Integer.parseInt(serverSelectionTimeOut));
            optionsBuilder.socketTimeout(Integer.parseInt(socketTimeOut));
            optionsBuilder.connectionsPerHost(Integer.parseInt(connections));
            optionsBuilder.maxConnectionIdleTime(Integer.parseInt(maxConnectionIdleTime));
            optionsBuilder.minConnectionsPerHost(Integer.parseInt(minConnectionsPerHost));
            if(Boolean.valueOf(ValidationProperties.getValue("clm.db.useSecondaryMongoForRead"))) {
                logger.info("Read is going for secondary mongoDB");
                optionsBuilder.readPreference(ReadPreference.secondaryPreferred());
            }


            MongoClientOptions options = optionsBuilder.build();
            mongoClient = new MongoClient(new ServerAddress(hostname, Integer.parseInt(port)), creds, options);

        } catch (Exception e) {
            logger.error("Error while connecting the Mongo DB {}", e);

        }
        return mongoClient;

    }



    public static MongoClient getMongoClient() {
        return mongoClient;
    }

In your code you are setting various MongoClientOptions, but you do not say what values you are using.在您的代码中,您正在设置各种 MongoClientOptions,但您没有说明您使用的是什么值。 Most likely one of the settings is causing the problem.最有可能的设置之一导致了问题。 My first guess would be that socketTimeout is too small, my second guess would be that connectionsPerHost is smaller than the maximum number of concurrent requests you receive in production.我的第一个猜测是 socketTimeout 太小,我的第二个猜测是 connectionPerHost 小于您在生产中收到的最大并发请求数。

I assume that testing in your production environment is not an option, so the first thing you should do is try and reproduce the problem in a test environment.我假设在您的生产环境中进行测试不是一种选择,因此您应该做的第一件事是尝试在测试环境中重现问题。 You can use the free JMeter tool to reproduce a certain load to your server.您可以使用免费的JMeter 工具将特定负载重现到您的服务器。 Use it's ramp-up feature to see if your problems start once you reach a certain load or if they occur at random.使用它的加速功能来查看您的问题是在达到特定负载后开始还是随机发生。

If you still have trouble finding out what exactly causes the problems, you can also try to comment out all your optionBuilder settings (so you'll be using all default settings).如果您仍然无法找出问题的确切原因,您还可以尝试注释掉所有 optionBuilder 设置(这样您将使用所有默认设置)。 If that fixes the problem, then you can set back your configuration options one-at-a-time to see which is the problematic one.如果这解决了问题,那么您可以一次设置一个配置选项以查看哪个是有问题的选项。

You must remove hibernate dependency from your project.您必须从项目中删除休眠依赖项。
I faced this problem and that was the solution.我遇到了这个问题,这就是解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM