java - Mongo Connection 在 RESTful API 中创建多次且从未发布

标签 java mongodb rest jersey morphia

我使用 Apache Jersey 编写了一个 RESTful API。我使用 MongoDB 作为我的后端。我使用 Morphia (v.1.3.4) 将 POJO 映射并保存到数据库。我尝试按照到处推荐的方式在我的 API 中遵循“1 个应用程序 1 个连接”,但我不确定我是否成功。我在 Tomcat 8 中运行我的 API。我还运行了 Mongostat 来查看详细信息和连接。 一开始,Mongostat 显示了 1 个到 MongoDB 服务器的连接。我使用 Postman 测试了我的 API,它工作正常。然后,我在 SoapUI 中创建了一个负载测试,我每秒模拟 100 个用户。我在 Mongostat 中看到了更新。 我看到有 103 个连接。这是显示此行为的 gif。

enter image description here

我不确定为什么会有这么多连接。有趣的是,mongo 连接数与我在 SoapUI 上创建的用户数成正比。这是为什么?我发现了其他类似的问题,但我想我已经实现了那里的建议。

Mongo connection leak with morphia

Spring data mongodb not closing mongodb connections

我的代码如下所示。

DatabaseConnection.java

// Some imports
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;
    }
}

PourService.java

@Secured
@Path("pours")
public class PourService {

final static Logger logger = Logger.getLogger(Pour.class);
private static final int POUR_SIZE = 30;

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response createPour(String request)
    {
        WebApiResponse response = new WebApiResponse();
        Gson gson = new GsonBuilder().setDateFormat("dd/MM/yyyy HH:mm:ss").create();
        String message = "Pour was not created.";
        HashMap<String, Object> data = null;
        try
        {
            Pour pour = gson.fromJson(request, Pour.class);

            // Storing the pour to 
            PourRepository pourRepository = new PourRepository();           
            String id = pourRepository.createPour(pour);

            data = new HashMap<String, Object>();
            if ("" != id && null != id)
            {
                data.put("id", id);
                message = "Pour was created successfully.";
                logger.debug(message);
                return response.build(true, message, data, 200);
            }

            logger.debug(message);
            return response.build(false, message, data, 500);
        }
        catch (Exception e)
        {
            message = "Error while creating Pour.";
            logger.error(message, e);
            return response.build(false, message, new Object(),500);
        }
    }

PourDao.java

public class PourDao extends BasicDAO<Pour, String>{

    public PourDao(Class<Pour> entityClass, Datastore ds) {
        super(entityClass, ds);
    }
}

PourRepository.java

public class PourRepository {

    private PourDao pourDao;

    final static Logger logger = Logger.getLogger(PourRepository.class);

    public PourRepository ()
    {
        try 
        {
            MongoClient mongoClient = DatabaseConnection.getMongoClient();
            Datastore ds = new Morphia().map(Pour.class)
                    .createDatastore(mongoClient, "tilt45");
            pourDao = new PourDao(Pour.class,ds);
        } 
        catch (Exception e) 
        {
            logger.error("Error while creating PourDao", e);
        }
    }

    public String createPour (Pour pour)
    {
        try
        {
            return pourDao.save(pour).getId().toString();
        }
        catch (Exception e)
        {
            logger.error("Error while creating Pour.", e);
            return null;
        }
    } 
 }

最佳答案

当我使用 Mongo+Morphia 时,我使用数据存储的工厂模式获得了更好的结果,而不是 MongoClient,例如,检查以下类:

public DatastoreFactory(String dbHost, int dbPort, String dbName) {
    final Morphia morphia = new Morphia();
    MongoClientOptions.Builder options = MongoClientOptions.builder().socketKeepAlive(true);
    morphia.getMapper().getOptions().setStoreEmpties(true);
    final Datastore store = morphia.createDatastore(new MongoClient(new ServerAddress(dbHost, dbPort), options.build()), dbName);
    store.ensureIndexes();
    this.datastore = store;
}

通过这种方法,每次您需要数据存储时,您都可以使用工厂提供的数据存储。当然,如果您使用支持工厂模式的框架/库(例如:HK2 with org.glassfish.hk2.api.Factory)和单例绑定(bind),这可以更好地实现。

此外,你可以查看MongoClientOptions的builder方法的文档,也许你可以在那里找到更好的连接控制。

关于java - Mongo Connection 在 RESTful API 中创建多次且从未发布,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44901376/

相关文章:

java - 从 ButtonGroup() 返回值

java - 如何避免在微调器中从 sqlite 获取双数据?

java - 如何在 GAE 上将数据存储游标与 jpa 一起使用

javascript - 如何根据条件设置 Mongoose 模式的默认属性值

javascript - mocha + mongodb 等待异步结果

java - 放心请求不起作用

java - java编译器从哪一行开始检查编码行

angularjs - 执行 PUT 请求 $resource 时 Angular 1.3 中的 $Promise 错误

angularjs - 如何从两个不同的 REST API 修改 Angular 中 $resource 的结果

api - Values.lazy 上的 NoSuchMethodError( Jersey 2.5.1)