MongoDB 在每秒 100 次写入时停滞,但基准测试显示每秒 54000 次写入

MongoDB 在每秒 100 次写入时停滞,但基准测试显示每秒 54000 次写入

我在 AWS EC2 m4.large 实例上运行 MongoDB(v3.4 社区版)。我按照此步骤安装它MongoDB 教程。我没有修改任何 MongoDB 配置。我没有配置任何副本集或分片。我有一个 Jersey API,它使用以下方式与 MongoDB 交互org.mongodb.morphia (v1.3.2) Java 驱动程序

我使用 SoapUI 创建了一个负载测试,其中我调用了 100 次 API,从而为 MongoDB 创建了 100 次写入操作(每次写入操作在一个集合中创建一个文档)。我运行了 24 小时的测试。最后,我看到我的 Web 服务器尝试与 Mongo 服务器通信,但连接超时,主机 CPU 以 100% 的运行速度运行。我得出结论,MongoDB 服务器正在阻塞。

然后我尝试了这个基准测试,仍然使用托管在 m4.large 上的数据库。在 923.133 秒内创建了 50,000,000 条记录,即每秒插入 54,113 条。速度快了 500 多倍!

如果 MongoDB 性能如此出色,那么为什么在使用 JAVA 驱动程序时,每秒插入 100 条数据就会卡住?Java 驱动程序慢吗?我对 Java 驱动程序的使用是否错误?我的 EC2 实例大小是否太小?添加复制(RAID 和副本集)是否有帮助?

我是 MongoDB 托管的新手,非常感谢您的学习帮助。

更新:

负载测试配置:

客户端:SoapUI (v5.3)、Web 服务器:Tomcat 8、Java:v1.8、MongoDB:v3.4。我的所有服务器都在 AWS 孟买地区运行。我在同一个 EC2 实例 (m4.large) 上托管 Web 服务器和 MongoDB 服务器,并在 Windows 机器 (t2.micro) 上运行客户端。

经过进一步调查,我认为瓶颈在于我的代码。我使用了蒙哥斯塔特实用程序来查看 mongodb 的行为。我发现,开始时有两个连接。一旦启动负载测试,连接数就会跳转到 102(即使每秒有 1000 个请求,连接数也不会超过 102,MongoDB 会在很长时间后关闭它们)。负载是每秒 100 个请求。以下是显示此行为的 gif。

在此处输入图片描述

我发现了一些有类似问题的问题,但答案并没有透露太多信息。我已经采纳了这些建议。以下是一些示例,

https://stackoverflow.com/questions/21580147/mongo-connection-leak-with-morphia

https://stackoverflow.com/questions/31469656/spring-data-mongodb-not-closing-mongodb-connections

Java代码:

创建连接:我按照 MongoDB 的建议为我的应用程序使用一个连接。实现单例模式。

public class DatabaseConnection {

    private static volatile MongoClient instance;
    private static String cloudhost="localhost";

    private DatabaseConnection() { }

    public synchronized static MongoClient getMongoClient() {
        if (instance == null ) {
            synchronized (DatabaseConnection.class) {
                if (instance == null) {
                    ServerAddress addr = new ServerAddress(cloudhost, 27017);
                    List<MongoCredential> credentialsList = new ArrayList<MongoCredential>();
                    MongoCredential credentia = MongoCredential.createCredential(
                        "test", "test", "test".toCharArray());
                    credentialsList.add(credentia);
                    instance = new MongoClient(addr, credentialsList); 

                }
            }
        }
        return instance;
    }
}

示例数据访问对象类:

import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.dao.BasicDAO;

import Sample;

public class SampleDao extends BasicDAO<Sample, String>{

    public SampleDao(Class<Sample> entityClass, Datastore ds) {
        super(entityClass, ds);
    }
}

示例存储库类:此类负责与数据库交互并持久保存文档

public class SampleRepository {

    private SampleDao sampleDao;

    public SampleRepository ()
    {
        try 
        {
            MongoClient mongoClient = DatabaseConnection.getMongoClient();
            Datastore ds = new Morphia().map(Pour.class)
                    .createDatastore(mongoClient, "test");
            sampleDao = new SampleDao(Sample.class,ds);
        } 
        catch (Exception e) 
        {
            logger.error("Error while creating SampleDao", e);
        }
    }

    public String createSample (Sample sample)
    {
        try
        {
            Sample2Repository repo = new Sample2Repository ();
            Sample2 sample2 = repo.getSample2(sample.getSampleId());
            Sample.setSample2Id(sample2.getId());

            retur sampleDao.save(sample).getId().toString();
        }
        catch (Exception e)
        {
            logger.error("Error while creating sample.", e);
            return null;
        }
    }
}

示例文档:我认为我的文档大小不会对 MongoDB 造成问题。负载测试期间没有调用其他查询。只有 CreateSample 操作正在运行。

{
    "sample2Id":"593e346cfeaa9e62d1706bb5"
    , "sample3Id" : "593e4159729f5d04db7b6da2"
    , "actualTime":"21/06/2017 09:18:00"
    , "uploadTime":"21/06/2017 09:18:00"
}

相关内容