繁体   English   中英

嵌入式fladdoodle MongoDB进程不会停止

[英]Embeded flapdoodle MongoDB process won't stop

我在我的应用程序中使用了一个flapdoodle 嵌入式 MongoDB实例。

嵌入式 MongoDB 启动并按预期工作,但是当应用程序停止或集成测试结束时,嵌入式实例的进程不会停止。

我正在使用下面的类来管理嵌入式 MongoDB 实例的状态。 是否缺少正确停止嵌入式 MongoDB 的内容? 我们可以将嵌入式 MongoDB 实例的进程作为守护进程启动(因此即使应用程序停止,它也不会继续运行)?

package ch.somePackage.configuration;

import com.mongodb.ConnectionString;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import de.flapdoodle.embed.mongo.MongodExecutable;
import de.flapdoodle.embed.mongo.MongodProcess;
import de.flapdoodle.embed.mongo.MongodStarter;
import de.flapdoodle.embed.mongo.config.IMongodConfig;
import de.flapdoodle.embed.mongo.config.MongodConfigBuilder;
import de.flapdoodle.embed.mongo.config.Net;
import de.flapdoodle.embed.mongo.distribution.Version;
import de.flapdoodle.embed.process.runtime.Network;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.Objects;

@Configuration
public class DbConfiguration  {

    final static Logger logger = LoggerFactory.getLogger(DbConfiguration.class);

    private static final ConnectionString CONNECTION_STRING = new ConnectionString("mongodb://localhost:12345/some-db");

    @Bean
    public MongoHolder mongoHolder() {
        return new MongoHolder();
    }

    public static class MongoHolder {

        private MongoClient mongoClient;
        private MongodExecutable mongodExecutable;
        private MongodProcess mongod;

        @PostConstruct
        public void init() throws IOException {
            final MongodStarter starter = MongodStarter.getDefaultInstance();

            final String bindIp = "localhost";
            final int port = 12345;
            final IMongodConfig mongodConfig = new MongodConfigBuilder()
                    .version(Version.Main.PRODUCTION)
                    .net(new Net(bindIp, port, Network.localhostIsIPv6()))
                    .build();

            try {
                mongodExecutable = starter.prepare(mongodConfig);
                mongod = mongodExecutable.start();
                mongoClient = new MongoClient(bindIp, port);
                logger.info("Started embedded mongo.");
            } catch (final Exception e) {
                e.printStackTrace();
            }
        }

        @PreDestroy
        public final synchronized void destroy() {
            if (mongodExecutable != null) {
                logger.info("Stopping embedded mongo.");
                mongoClient.close();
                mongodExecutable.stop();
                mongod.stop();
                logger.info("Stopped embedded mongo.");
            }
        }

        public MongoClient getMongoClient() {
            return mongoClient;
        }
    }

    @Bean
    public MongoDatabase mongoDatabase(final MongoHolder mongoHolder) {
        return mongoHolder.getMongoClient().getDatabase(Objects.requireNonNull(CONNECTION_STRING.getDatabase()));
    }
}

在使用 fladdoodle 嵌入式 MongoDB 进行开发以及通过gradle bootRun运行 Spring 应用程序时,我遇到了同样的问题。 停止该进程后,MongoDB 服务器存活了下来,并且越来越多的运行实例堆积起来,MongoDB 中的数据也保留了下来。

经过一番搜索和尝试后,我能够根据https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/issues/212中提供的答案解决问题

我的 MongoDB 配置类看起来非常相似,解决方案的关键是等待MongodProcess mongod通过检查mongod.isProcessRunning()正确停止。 周围的while循环有点hacky,但它对我有用:

@Configuration
@Profile("dev")
public class EmbeddedMongoConfig {

    Logger logger = LoggerFactory.getLogger(EmbeddedMongoConfig.class);

    private static final String CONNECTION_STRING = "mongodb://%s:%d";
    private static final String HOST = "localhost";
    private static final int PORT = 27017;


    private MongodExecutable mongodExecutable;
    private MongodProcess mongod;
    private MongoClient client;

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {

        ImmutableMongodConfig mongoDbConfig = MongodConfig.builder()
                .version(Version.Main.PRODUCTION)
                .net(new Net(HOST, PORT, Network.localhostIsIPv6()))
                .build();

        MongodStarter starter = MongodStarter.getDefaultInstance();

        mongodExecutable = starter.prepare(mongoDbConfig);
        mongod = mongodExecutable.start();
        client = MongoClients.create(String.format(CONNECTION_STRING, HOST, PORT));

        return new MongoTemplate( client, "sampledatabase");
    }


    /*
     * solution found here: https://github.com/flapdoodle-oss/de.flapdoodle.embed.mongo/issues/212
     */
    @PreDestroy
    public void shutdownGracefully() {
        if (client != null)
            client.close();
        if (mongod != null)
            try {
                mongod.stop();
            } catch (IllegalStateException e) {
                logger.error("Can't stop mongod", e);
            }
        if (mongod != null) {
            int limit = 5;
            int counter = 0;
            while (mongod.isProcessRunning() && counter < limit) {
                try {
                    counter++;
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
        if (mongodExecutable != null) {
            try {
                mongodExecutable.stop();
            } catch (IllegalStateException e) {
                logger.error("Can't stop mongodExecutable", e);
            }
        }
    }
}

也许它仍然可以帮助遇到同样问题的其他人。

暂无
暂无

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

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