mongodb连接不上的问题Exception thrown during connection pool background maintenance task

最近做spring+spring boot1.2 升到spring boot 2.2版本的时候发现, mongodb一直连不上,主要是原有的阿里云配置连接,和腾讯云的相差很大,尤其是连接加密方面,经过多方定位,排查连接方法,和各种方式,终于查出mongodb的连接配置有一个地方是不同的,下面是报错:

Exception thrown during connection pool background maintenance task
2021-09-18T02:08:44.965869943Z 
2021-09-18T02:08:44.965873409Z com.mongodb.MongoSocketOpenException: Exception opening socket
2021-09-18T02:08:44.965876735Z     at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:70)
2021-09-18T02:08:44.965879419Z     at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:128)
2021-09-18T02:08:44.965881994Z     at com.mongodb.internal.connection.UsageTrackingInternalConnection.open(UsageTrackingInternalConnection.java:50)
2021-09-18T02:08:44.965884639Z     at com.mongodb.internal.connection.DefaultConnectionPool$UsageTrackingInternalConnectionItemFactory.create(DefaultConnectionPool.java:530)
2021-09-18T02:08:44.965887404Z     at com.mongodb.internal.connection.DefaultConnectionPool$UsageTrackingInternalConnectionItemFactory.create(DefaultConnectionPool.java:518)
2021-09-18T02:08:44.965890159Z     at com.mongodb.internal.connection.ConcurrentPool.createNewAndReleasePermitIfFailure(ConcurrentPool.java:181)
2021-09-18T02:08:44.965892835Z     at com.mongodb.internal.connection.ConcurrentPool.ensureMinSize(ConcurrentPool.java:175)
2021-09-18T02:08:44.96589544Z     at com.mongodb.internal.connection.DefaultConnectionPool$3.run(DefaultConnectionPool.java:317)
2021-09-18T02:08:44.965898034Z     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
2021-09-18T02:08:44.965900659Z     at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
2021-09-18T02:08:44.965903183Z     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)

2021-09-18T02:08:44.965915216Z     at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
2021-09-18T02:08:44.965917882Z     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
2021-09-18T02:08:44.965920366Z     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
2021-09-18T02:08:44.96592286Z     at java.lang.Thread.run(Thread.java:745)
2021-09-18T02:08:44.965925305Z Caused by: java.net.SocketTimeoutException: connect timed out
2021-09-18T02:08:44.96592777Z     at java.net.PlainSocketImpl.socketConnect(Native Method)
2021-09-18T02:08:44.965930234Z     at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
2021-09-18T02:08:44.965932729Z     at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
2021-09-18T02:08:44.965935835Z     at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
2021-09-18T02:08:44.965938369Z     at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
2021-09-18T02:08:44.965940805Z     at java.net.Socket.connect(Socket.java:589)
2021-09-18T02:08:44.965943259Z     at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:64)
2021-09-18T02:08:44.965945724Z     at com.mongodb.internal.connection.SocketStream.initializeSocket(SocketStream.java:79)
2021-09-18T02:08:44.965948208Z     at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:65)
2021-09-18T02:08:44.965950683Z     ... 14 common frames omitted
2021-09-18T02:08:44.965953117Z 

腾讯的连接方式:

MongoConfiguration 

 
import com.mongodb.*;
import com.mongodb.client.MongoDatabase;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * mongoDB配置
 * @author chengge
 */
@Configuration
@ConditionalOnClass(MongoDbFactory.class)
public class MongoConfiguration {

    @Bean
    @ConfigurationProperties(value = MongoProperties.MONGO_PROPERTIES_PREFIX)
    public MongoProperties getMongoSettingsProperties(){
        return new MongoProperties();
    }


    /**
     * 覆盖容器中默认的MongoDbFacotry Bean
     */
    public MongoDbFactory mongoDbFactory(MongoProperties properties) {
        MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
        builder.connectionsPerHost(properties.getMaxConnectionsPerHost());
        builder.minConnectionsPerHost(properties.getMinConnectionsPerHost());
        builder.threadsAllowedToBlockForConnectionMultiplier(
                properties.getThreadsAllowedToBlockForConnectionMultiplier());
        builder.serverSelectionTimeout(properties.getServerSelectionTimeout());
        builder.maxWaitTime(properties.getMaxWaitTime());
        builder.maxConnectionIdleTime(properties.getMaxConnectionIdleTime());
        builder.maxConnectionLifeTime(properties.getMaxConnectionLifeTime());
        builder.connectTimeout(properties.getConnectTimeout());
        builder.socketTimeout(properties.getSocketTimeout());
        builder.sslEnabled(properties.getSslEnabled());
        builder.sslInvalidHostNameAllowed(properties.getSslInvalidHostNameAllowed());
        builder.alwaysUseMBeans(properties.getAlwaysUseMBeans());
        builder.heartbeatFrequency(properties.getHeartbeatFrequency());
        builder.minHeartbeatFrequency(properties.getMinHeartbeatFrequency());
        builder.heartbeatConnectTimeout(properties.getHeartbeatConnectTimeout());
        builder.heartbeatSocketTimeout(properties.getHeartbeatSocketTimeout());
        builder.localThreshold(properties.getLocalThreshold());
//         创建认证客户端
        MongoClientURI connStr = new MongoClientURI(properties.getAddressList(),builder);
        MongoClient mongoClient = new MongoClient(connStr);

//        // 创建MongoDbFactory
        MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, properties.getDbName());
        return mongoDbFactory;
    }


    //第一个数据库 默认作为主数据库 需要添加注解 @Primary ,后面的数据库不需要这个注解
    @Bean
    public  MongoTemplate getMongoTemplate() {
        return new MongoTemplate(mongoDbFactory(getMongoSettingsProperties()) );
    }

}

 MongoProperties 


import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.ArrayList;

/**
 * mongoDB配置
 * @author chengge
 */
@Setter
@Getter
@ToString
public class MongoProperties {
    public static final String MONGO_PROPERTIES_PREFIX = "spring.mongo";
    private Integer minConnectionsPerHost = 0;
    private Integer maxConnectionsPerHost = 100;
    private Integer threadsAllowedToBlockForConnectionMultiplier = 5;
    private Integer serverSelectionTimeout = 30000;
    private Integer maxWaitTime = 120000;
    private Integer maxConnectionIdleTime = 0;
    private Integer maxConnectionLifeTime = 0;
    private Integer connectTimeout = 10000;
    private Integer socketTimeout = 0;
    private Boolean socketKeepAlive = false;
    private Boolean sslEnabled = false;
    private Boolean sslInvalidHostNameAllowed = false;
    private Boolean alwaysUseMBeans = false;
    private Integer heartbeatConnectTimeout = 20000;
    private Integer heartbeatSocketTimeout = 20000;
    private Integer minHeartbeatFrequency = 500;
    private Integer heartbeatFrequency = 10000;
    private Integer localThreshold = 15;


    /**
     * 连接最大数
     */
    private Integer connectionsPerHost = 50;

    /**
     * 等待连接数
     */
    private Integer waitingConnectionsNumber = 50;

    /**
     * mongo的jar包
     */
    private String mapPackage;
    private String authenticationDatabase;
    private String address;
    private String dbName;
    private String auth;
    private String password;
    private int port;

    private String addressList;

}

application.yml


spring:
  mongo:
    mapPackage: com.*.*.model
    address: localhost:27017
    auth: user
    password: password
    dbName: db-name
    addressList: mongodb://user:password@localhost:27017/db_name?authSource=admin&replicaSet=cmgo-79qlu0kn_0

阿里的配置文件:

MongoConfiguration

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * mongoDB配置
 * @author chengge
 */
@Configuration
@ConditionalOnClass(MongoDbFactory.class)
public class MongoConfiguration {

    @Bean
    @ConfigurationProperties(value = MongoProperties.MONGO_PROPERTIES_PREFIX)
    public MongoProperties getMongoSettingsProperties(){
        return new MongoProperties();
    }

    /**
     * 覆盖容器中默认的MongoDbFacotry Bean
     */
    public MongoDbFactory mongoDbFactory(MongoProperties properties) {
        MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
        builder.connectionsPerHost(properties.getMaxConnectionsPerHost());
        builder.minConnectionsPerHost(properties.getMinConnectionsPerHost());
        builder.threadsAllowedToBlockForConnectionMultiplier(
                properties.getThreadsAllowedToBlockForConnectionMultiplier());
        builder.serverSelectionTimeout(properties.getServerSelectionTimeout());
        builder.maxWaitTime(properties.getMaxWaitTime());
        builder.maxConnectionIdleTime(properties.getMaxConnectionIdleTime());
        builder.maxConnectionLifeTime(properties.getMaxConnectionLifeTime());
        builder.connectTimeout(properties.getConnectTimeout());
        builder.socketTimeout(properties.getSocketTimeout());
        // builder.socketKeepAlive(properties.getSocketKeepAlive());
        builder.sslEnabled(properties.getSslEnabled());
        builder.sslInvalidHostNameAllowed(properties.getSslInvalidHostNameAllowed());
        builder.alwaysUseMBeans(properties.getAlwaysUseMBeans());
        builder.heartbeatFrequency(properties.getHeartbeatFrequency());
        builder.minHeartbeatFrequency(properties.getMinHeartbeatFrequency());
        builder.heartbeatConnectTimeout(properties.getHeartbeatConnectTimeout());
        builder.heartbeatSocketTimeout(properties.getHeartbeatSocketTimeout());
        builder.localThreshold(properties.getLocalThreshold());
        MongoClientOptions mongoClientOptions = builder.build();

        // MongoDB地址列表
        List serverAddresses = new ArrayList<>();
        for (String address : properties.getAddress()) {
            String[] hostAndPort = address.split(":");
            String host = hostAndPort[0];
            Integer port = Integer.parseInt(hostAndPort[1]);
            ServerAddress serverAddress = new ServerAddress(host, port);
            serverAddresses.add(serverAddress);
        }

        // 连接认证
        MongoCredential mongoCredential = MongoCredential.createCredential(properties.getAuth()[0], properties.getDbName(),  properties.getPassword());
//         创建认证客户端
        MongoClient mongoClient = new MongoClient(serverAddresses, mongoCredential, mongoClientOptions);


//        // 创建MongoDbFactory
        MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, properties.getDbName());
        return mongoDbFactory;
    }

    //第一个数据库 默认作为主数据库 需要添加注解 @Primary ,后面的数据库不需要这个注解
    @Bean
        public  MongoTemplate getMongoTemplate() {
        return new MongoTemplate(mongoDbFactory(getMongoSettingsProperties()));
    }

}
MongoProperties

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.util.ArrayList;

/**
 * mongoDB配置
 * @author chengge
 */
@Setter
@Getter
@ToString
public class MongoProperties {
    public static final String MONGO_PROPERTIES_PREFIX = "spring.mongo";
    private Integer minConnectionsPerHost = 0;
    private Integer maxConnectionsPerHost = 100;
    private Integer threadsAllowedToBlockForConnectionMultiplier = 5;
    private Integer serverSelectionTimeout = 30000;
    private Integer maxWaitTime = 120000;
    private Integer maxConnectionIdleTime = 0;
    private Integer maxConnectionLifeTime = 0;
    private Integer connectTimeout = 10000;
    private Integer socketTimeout = 0;
    private Boolean socketKeepAlive = false;
    private Boolean sslEnabled = false;
    private Boolean sslInvalidHostNameAllowed = false;
    private Boolean alwaysUseMBeans = false;
    private Integer heartbeatConnectTimeout = 20000;
    private Integer heartbeatSocketTimeout = 20000;
    private Integer minHeartbeatFrequency = 500;
    private Integer heartbeatFrequency = 10000;
    private Integer localThreshold = 15;


    /**
     * 连接最大数
     */
    private Integer connectionsPerHost = 50;

    /**
     * 等待连接数
     */
    private Integer waitingConnectionsNumber = 50;

    /**
     * mongo的jar包
     */
    private String mapPackage;
    private String authenticationDatabase;
    private ArrayList address;
    private String dbName;
    private String[] auth;
    private char[] password;
    private int port;
}

application.yml

spring:
  mongo:
    mapPackage: com.*.*.model
    address: localhost:27017
    auth: user
    password: password
    dbName: db-name

以上的方式主要是因为腾讯的mongodb对3.0和4.0的版本连接做了很大的限制,而阿里云则对mongodb的连接没有做这么大的限制。

好啦以上就是我个人所得经验,如果有不足的地方,或者有需要改进的地方和更好的建议,请大家联系我哦。

都看到这里了,点个关注把。

你可能感兴趣的:(mongodb,java,数据库)