У меня есть многопоточное приложение, которое выполняет сотни транзакций в секунду, но через некоторое время производительность падает, и запросы выполняются слишком долго. Я работал над оптимизацией соединения с помощью следующего кода, чтобы избежать ошибок, но это привело к низкой производительности.
Мои запросы варьируются от вставки, удаления и многократного обновления; коллекции не превышают 100 000 строк.
У меня есть кластер из 4 виртуальных машин для mongoldb, каждая из которых имеет 4 ядра и 28 ГБ оперативной памяти в Azure. Я построил кластер, используя производство bitnami (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();
Я не использую никаких индексов, и вот мой поток приложений:
- Я использую сказки БД для организации очереди и обработки сообщений. Каждое задание сохраняется в отдельной коллекции с документом для каждого сообщения, который выглядит следующим образом (статус «готов» для сообщений на данном этапе):
{
"_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"
}
- Затем я перемещаю пакеты из каждого задания в соответствии с их приоритетами из состояния «готово» в «в очереди» и добавляю их в очередь в памяти для обработки:
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);
}
- Затем другой поток отправляет фактические сообщения из очереди в памяти и обновляет статус каждого сообщения отдельно (отправлено/сбой); Я добавляю индекс для этого сообщения в отдельную таблицу, чтобы я мог найти его, как только отправитель отправит мне окончательный статус.
- Наконец, я получаю от отправителя окончательный результат о сообщении (доставлено/не доставлено) и соответствующим образом обновляю это сообщение, а затем удаляю индекс из коллекции (job_index) на предыдущем шаге.
========================= ОБНОВЛЕНИЕ:=============== =======
Я заметил, что получил эту ошибку в журналах Java:
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)
А вот мой конфиг MongoDB:
# 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
mongod —profile 1 —slowms 20
. См. stackoverflow.com/a/18451741/4148708. - person evilSnobu   schedule 10.09.2016