Я хочу проверить пропускную способность моей системы, которая подключена к базе данных postgresql. Моя система состоит из 2 основных компонентов: ThreadPoolExecutor как newFixedThreadPool с максимум 10 потоками и PGPoolingDataSource, называемый connectionPool, который имеет максимум 10 подключений к базе данных. Я вызываю хранимые процедуры в базе данных postgres, хранимая процедура выполняет простую вставку и возвращает сообщение об ошибке, если вставка не удалась. Выполнение одного вызова этой хранимой процедуры занимает около 20-30 мс.
Система работает следующим образом: основной поток создает задачи сообщений и передает их в пул потоков. Задача сообщения делает следующее: получает соединение из пула соединений и вызывает хранимую процедуру на сервере postgres. Он ждет ответа, а затем задача завершается. Поток в пуле потоков теперь может работать над новой задачей сообщения.
Теперь я думаю, что это должно работать нормально, и в какой-то степени это работает. Это только очень медленно, и я абсолютно не знаю, почему. Используя следующий код, я записываю около 300-500 вставок в секунду, когда должно быть 6000 вставок в секунду. Понятия не имею почему. При использовании системного монитора я вижу, что все процессоры загружены примерно на 20%. Когда я раскомментирую раздел, обозначенный (1), 1 процессор загружается на 100%, а остальные - около 0%, что для меня загадка.
Если кто-нибудь может поделиться светом о том, что я делаю неправильно, это было бы здорово. Это мой сервер postgres настроен неправильно? Когда я использую команду top, она показывает, что java использует около 20% процессора, и есть 8 процессов postgres, каждый из которых использует около 3%. (Я использую Ubuntu 14.04, используя Eclipse).
Вот мой код MainTester, содержащий основную функцию. Он создает пул потоков и пул соединений с базой данных.
public class MainTester {
public static ThreadPoolExecutor threadPoolExecutor;
public static PGPoolingDataSource connectionPool;
public static void main(String[] args) {
establishConnectionPool(10);
threadPoolExecutor = (ThreadPoolExecutor)
Executors.newFixedThreadPool(10);
Operator operator = new Operator(1, 2, 30);
operator.run();
// i created an other thread here before.
//Now I just use the main thread to run the operator
}
private static void establishConnectionPool(int nrOfConnections)
{
connectionPool = new PGPoolingDataSource();
connectionPool.setDataSourceName("ConnectionPool");
connectionPool.setServerName(dbServerName);
connectionPool.setDatabaseName(dbName);
connectionPool.setUser(dbUser);
connectionPool.setPassword(dbPassword);
connectionPool.setMaxConnections(nrOfConnections);
}
Это мой код оператора. Он порождает задачи сообщений и передает их в пул потоков. Я хочу, чтобы он работал в течение 2 минут, а затем проверил количество вставленных сообщений. Я хочу, чтобы очередь пула потоков всегда была заполнена, поэтому я проверяю, имеет ли очередь пула потоков менее 1000 задач. Если их меньше, я создаю новые задачи для пула потоков.
public class Operator implements Runnable{
private int minutesToRun = 2;
private void run () {
long startTime = System.currentTimeMillis();
while (System.currentTimeMillis() - startTime < minutesToRun * 60 * 1000 + 10) {
while(MainTester.threadPoolExecutor.getQueue().size() < 1000) {
MessageTask messageTask = new MessageTask(QueueOperation.SEND, 1, 1, 1, "abc");
MainTester.threadPoolExecutor.execute(messageTask);
}
try { // (1)
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
(1) когда я не сплю здесь, системный монитор показывает, что 1 процессор на 100%, остальные на 0%. Это не имеет смысла для меня. Конечно, этот метод полностью занял бы один процессор, но потоки из пула потоков должны работать на другом процессоре, нет?
Вот мой код для задачи сообщения:
public class MessageTask implements Runnable {
private QueueOperation operation;
private int senderId;
private int receiverId;
private int queueId;
private String message;
public MessageTask (QueueOperation op, int senderId, int receiverId, int queueId, String message)
{
operation = op;
this.senderId = senderId;
this.receiverId = receiverId;
this.queueId = queueId;
this.message = message;
}
@Override
public void run() {
Connection connection = null;
try {
connection = MainTester.connectionPool.getConnection();
} catch (SQLException e) {
e.printStackTrace();
}
try{
Statement statement = connection.createStatement();
String dbStoredProcedure = "SELECT send(" + senderId + "," + receiverId + "," + queueId + "," + "'"+message+"'"+ ");";;
ResultSet resultSet = statement.executeQuery(dbStoredProcedure);
resultSet.next();
String dbResponse = resultSet.getString(1);
}
catch (SQLException e) {
}
finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Итак, мои вопросы: почему это так медленно? Почему все 8 моих процессоров загружены только на 20%? Возможно, я неправильно настроил свой сервер postgresql? Я ничего не менял в конфигурации по умолчанию. Я неправильно понял, как работает пул потоков? Или пул соединений не работает так, как я предполагал?
INSERT
? Когда вы вызываете SP изSELECT
, всегда есть неотъемлемая медлительность из-за переключения контекста. Кроме того, отсутствие переменных связывания еще больше замедляет синтаксический анализ, который должен выполнить Postgres перед выполнением оператора. - person Mick Mnemonic   schedule 01.11.2015