Ich habe eine Multithread-App, die Hunderte von Transaktionen pro Sekunde ausführt, aber nach einer Weile die Leistung sinkt und die Abfragen dauern zu lange, um auszuführen. Ich habe daran gearbeitet, die Verbindung mit dem folgenden Code zu optimieren, um Fehler zu vermeiden, aber dies führte zu einer schlechten Leistung.Mongodb-Abfragen sind sehr langsam
Meine Abfragen variieren von Einfügungen, Löschen und Multi-Update; Sammlungen überschreiten nicht 100.000 Zeilen.
Ich habe einen Cluster von 4 VMs für Mongoldb jeder hat 4 Kerne und 28 GB Ram auf Azure. Ich baute den Cluster bitnami Produktion (https://azure.microsoft.com/en-us/marketplace/partners/bitnami/production-mongodbdefault/)
private static MongoClientOptions options = MongoClientOptions.builder()
.connectionsPerHost(1000)
.threadsAllowedToBlockForConnectionMultiplier(15)
.connectTimeout(60 * 1000)
.maxWaitTime(60 * 1000)
.socketTimeout(60 * 1000)
.connectTimeout(60 * 1000)
.build();
Ich benutze keine Indizes verwenden und hier ist meine App Flow:
- sind die db Geschichten zum Einreihen und Verarbeitung msgs verwenden. Jeder Auftrag wird in einer separaten Sammlung gespeichert, mit einem Dokument für jeden msg die wie folgt aussieht (Status ‚bereit‘ für die msgs in diesem Stadium):
{
"_id": ObjectId("57cd303743ffe80f3728fcf5"),
"_class": "com.mongodb.BasicDBObject",
"job_id": "57cd3031d9991f8639487013",
"priority": 1,
"title": "1",
"sender_id": "sender 1",
"account_id": "57c2d556d9991fbc15897275",
"schedule_date": ISODate("2016-09-05T08:43:00Z"),
"utf8": false,
"content": "text to be sent",
"number": "962799000001",
"status": "ready",
"user_id": "57c2d602d9991fbc1589727b",
"adv": true,
"number_of_sms_msgs": 1,
"uuid": "57cd3031d9991f8639487013_57cd303743ffe80f3728fcf5",
"msg_id": "1955559517"
}
- Dann bin ich Chargen von jedem Auftrag nach ihren Prioritäten von Status ‚bereit‘ zu ‚Warteschlange‘ und fügen sie sie auf-Speicherwarteschlange zu bewegen verarbeitet werden:
List<DBObject> batch = scaffoldingRepository.findPageNoSort(dataType, page, next_batch_size, query, null);
if (batch != null && batch.size() > 0) {
BasicDBList ids = new BasicDBList();
for (final DBObject msg : batch) {
msg.put("status", "queued");
msg.put("uuid", job_id + "_" + msg.get("_id"));
ids.add(new ObjectId(msg.get("_id").toString()));
}
BasicDBObject search = new BasicDBObject();
search.put("_id", new BasicDBObject("$in", ids));
BasicDBObject update = new BasicDBObject();
update.put("$set", new BasicDBObject("status", "queued"));
scaffoldingRepository.updateObjects(search, update, dataType);
}
- Dann sendet ein anderer Thread die aktuellen Nachrichten aus der On-Memory-Queue und aktualisiert eac h msg's Status getrennt (gesendet/fehlgeschlagen); Ich füge einen Index für diese Nachricht in einer separaten Tabelle hinzu, damit ich es finden kann, sobald der Absender mir den endgültigen Status zurücksendet.
- Schließlich bekomme ich ein Endergebnis vom Absender über die msg (geliefert/nicht geliefert) und ich aktualisiere diese Nachricht entsprechend, dann entfernen Sie den Index aus der Sammlung (Job_Index) im vorherigen Schritt.
========================== UPDATE: ============= =========
ich bemerkte, dass ich in Java-Protokolle diesen Fehler bekam:
com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message
at com.mongodb.connection.InternalStreamConnection.translateReadException(InternalStreamConnection.java:475)
at com.mongodb.connection.InternalStreamConnection.receiveMessage(InternalStreamConnection.java:226)
at com.mongodb.connection.UsageTrackingInternalConnection.receiveMessage(UsageTrackingInternalConnection.java:105)
at com.mongodb.connection.DefaultConnectionPool$PooledConnection.receiveMessage(DefaultConnectionPool.java:438)
at com.mongodb.connection.WriteCommandProtocol.receiveMessage(WriteCommandProtocol.java:262)
at com.mongodb.connection.WriteCommandProtocol.execute(WriteCommandProtocol.java:104)
at com.mongodb.connection.UpdateCommandProtocol.execute(UpdateCommandProtocol.java:64)
at com.mongodb.connection.UpdateCommandProtocol.execute(UpdateCommandProtocol.java:37)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:168)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:289)
at com.mongodb.connection.DefaultServerConnection.updateCommand(DefaultServerConnection.java:143)
at com.mongodb.operation.UpdateOperation.executeCommandProtocol(UpdateOperation.java:76)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:142)
at com.mongodb.operation.BaseWriteOperation$1.call(BaseWriteOperation.java:134)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:232)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:223)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:134)
at com.mongodb.operation.BaseWriteOperation.execute(BaseWriteOperation.java:61)
at com.mongodb.Mongo.execute(Mongo.java:827)
at com.mongodb.Mongo$2.execute(Mongo.java:810)
at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:333)
at com.mongodb.DBCollection.updateImpl(DBCollection.java:495)
at com.mongodb.DBCollection.update(DBCollection.java:455)
at com.mongodb.DBCollection.update(DBCollection.java:432)
at com.mongodb.DBCollection.update(DBCollection.java:522)
at com.mongodb.DBCollection.updateMulti(DBCollection.java:552)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Und hier ist meine MongoDB config:
# mongod.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# Where and how to store data.
storage:
dbPath: /opt/bitnami/mongodb/data/db
journal:
enabled: true
#engine:
mmapv1:
smallFiles: true
# wiredTiger:
# where to write logging data.
systemLog:
destination: file
logAppend: true
path: /opt/bitnami/mongodb/logs/mongodb.log
# network interfaces
net:
port: 27017
bindIp: 0.0.0.0
unixDomainSocket:
enabled: true
pathPrefix: /opt/bitnami/mongodb/tmp
# replica set options
replication:
replSetName: replicaset
# process management options
processManagement:
fork: false
pidFilePath: /opt/bitnami/mongodb/tmp/mongodb.pid
# set parameter options
setParameter:
enableLocalhostAuthBypass: true
# security options
security:
authorization: disabled
#keyFile: replace_me
#profiling
#operationProfiling:
#slowOpThresholdMs: 100
#mode: slowOp
Das Wichtigste zuerst würde ich nehmen ein Mongo-Profil und sehen, wer der Engpass ist - Mongo oder Ihr Anwendungscode. So etwas wie 'mongod -profile 1 -slowms 20'. Siehe http://stackoverflow.com/a/18451741/4148708 – evilSnobu