使用JMeter查询MongoDB文档:连接测试通过但数据查询超时的问题求助
Alright, let's dig into this issue. Your connection test passes, but the query fails with a "connection forcibly closed" timeout—this usually happens when the connection you're reusing has been dropped by the server or network, even though the initial connection worked. Here are the key fixes and checks to try:
MongoCollection object in JMeter variables JMeter's variables are shared across thread iterations, but MongoCollection (and even MongoDatabase) objects can become stale if the underlying connection is closed by the server. Instead, store the thread-safe MongoClient and fetch the database/collection fresh for each query.
Update your connection code to store MongoClient:
import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClient; import com.mongodb.MongoClientSettings; import com.mongodb.ServerAddress; import com.mongodb.client.MongoDatabase; import com.mongodb.client.MongoCollection; import org.bson.Document; import java.util.Arrays; try{ MongoClientSettings settings = MongoClientSettings.builder() .applyToClusterSettings {builder -> builder.hosts(Arrays.asList(new ServerAddress(vars.get("mongoHost"),vars.get("mongoPort").toInteger())))} .build(); MongoClient mongoClient = MongoClients.create(settings); vars.putObject("mongoClient", mongoClient); // Store the client instead of collection MongoDatabase database = mongoClient.getDatabase(vars.get("databaseName")); MongoCollection<Document> collection = database.getCollection(vars.get("collectionName")); return "Connected to " + vars.get("collectionName"); } catch (Exception e) { SampleResult.setSuccessful(false); SampleResult.setResponseCode("500"); SampleResult.setResponseMessage("Exception: " + e); }
Update your query code to fetch fresh collection each time:
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import static com.mongodb.client.model.Filters.*; import org.bson.Document; try { MongoClient mongoClient = vars.getObject("mongoClient"); // Fetch database and collection fresh for this query MongoCollection<Document> collection = mongoClient.getDatabase(vars.get("databaseName")) .getCollection(vars.get("collectionName")); Document result = collection.find(eq("city","CUSHMAN")).first(); if (result != null) { vars.put("exampleDocumentId", result.get("_id").toString()); return "Document with id=" + result.get("_id") + " found"; } else { SampleResult.setSuccessful(false); SampleResult.setResponseMessage("No document matching filter 'city=CUSHMAN' found"); return "No matching document found"; } } catch (Exception e) { SampleResult.setSuccessful(false); SampleResult.setResponseCode("500"); SampleResult.setResponseMessage("Exception: " + e); }
MongoDB servers often close idle connections after a timeout (default is 30 minutes, but some environments set it shorter). Add connection pool and socket settings to your MongoClientSettings to match server behavior and detect stale connections:
import java.util.concurrent.TimeUnit; // ... rest of imports MongoClientSettings settings = MongoClientSettings.builder() .applyToClusterSettings {builder -> builder.hosts(Arrays.asList(new ServerAddress(vars.get("mongoHost"),vars.get("mongoPort").toInteger())))} .applyToConnectionPoolSettings(builder -> { builder.maxSize(10) // Adjust based on your JMeter thread count .minSize(2) .maxIdleTime(60, TimeUnit.SECONDS) // Match or be shorter than server's idle timeout .maxWaitTime(30, TimeUnit.SECONDS); }) .applyToSocketSettings(builder -> { builder.connectTimeout(10, TimeUnit.SECONDS) .readTimeout(10, TimeUnit.SECONDS); }) .build();
The error "An existing connection was forcibly closed by the remote host" often points to a firewall or proxy dropping idle connections. If your JMeter instance is running outside the MongoDB server's network:
- Verify that the firewall allows sustained connections (not just initial handshakes)
- Add a periodic "keep-alive" query in your JMeter test (e.g., a simple
collection.countDocuments()run every few minutes) to prevent connections from going idle
If your MongoDB requires authentication, your initial connection might have passed, but the credential could be invalid for the query (unlikely, but worth checking). Add authentication to your MongoClientSettings if needed:
import com.mongodb.MongoCredential; // ... rest of imports MongoCredential credential = MongoCredential.createCredential( vars.get("mongoUser"), vars.get("databaseName"), vars.get("mongoPassword").toCharArray() ); MongoClientSettings settings = MongoClientSettings.builder() .credential(credential) // ... other settings .build();
Start with the first fix (storing MongoClient instead of MongoCollection)—that's the most common cause of this issue in JMeter tests. If that doesn't resolve it, move on to adjusting connection pool settings and checking network rules.
内容的提问来源于stack exchange,提问作者quickshekhar

