vert.x и BIO-потоки

1

В последнее время я начал изучать reactive, event-driven, неблокирующие Java-фреймворки, и есть тот, который поймал мой взгляд - vert.x

Я думаю, что один и тот же вопрос может быть применен к akka (Play framework), потому что их философия или одна из целей одна и та же - и это сокращение числа потоков и, следовательно, повышение масштабируемости приложения.

vert.x предполагает, что количество потоков, которое он потребляет, эквивалентно количеству ядер ЦП, но также имеет в виду, что иногда вам приходится выполнять операцию блокировки, поэтому он побуждает разработчика выполнять операцию блокировки на отдельном рабочем потоке ( рабочий вертикаль в терминах vert.x).

И это, когда мы приходим к моему вопросу:

  • если я должен выполнять блокировку операций ввода-вывода в новом отдельном потоке, это означает, что каждый пользователь, выполняющий операцию блокировки, имеет новый поток, и поэтому число потоков снова становится равным количеству пользователей, как в классической модели потоковой блокировки?

Реальный пример - это запрос JDBC - если 1000 одновременных пользователей запрашивают базу данных SQL через JDBC, каждый пользователь создает свой рабочий поток для этой операции блокировки. С моей точки зрения, нет нити, экономящей масштабируемость или экономии памяти по сравнению с классической моделью блокирующих потоков. Я должен что-то упустить... Или нет? Заранее благодарю за все ответы.

Теги:
multithreading
vert.x
akka

4 ответа

2
Лучший ответ

Нет смысла запускать 1000 параллельных потоков запросов в базу данных SQL - только потому, что типичная база данных не может переносить так много одновременных соединений, типичное число - 10-15. Решение состоит в организации специального пула потоков, где каждый поток имеет открытое соединение и обслуживает задачи, которые обращаются к базе данных. Задачи отправляются в общую очередь блокировки и рабочие потоки, считанные из этой очереди в цикле. Задачи - это примеры

interface DBRunnable {
  public void run(Connection conn);
}

рабочие потоки передают свое соединение с задачами:

public void run() {
  Connection conn = DriverManager.getConnection(...);
  while (true) {
     DBRunnable task=queue.take();
     task.run(conn);
  }
}
  • 0
    Совместите количество потоков в пуле потоков с размером пула соединений JDBC.
0

Как и другие, пожалуйста, ознакомьтесь с драйверами async для mysql и postgres, оба из которых имеют клиент, специально созданный для vert.x. Эти 2 базы данных охватывают большинство случаев использования для RDMS.

Другим неблокирующим вариантом является MongoDB, у которого есть настроенный неблокирующий клиент vert.x. Отлично работает, но, конечно, не SQL.

0

Как уже говорилось ранее, вы должны использовать пул соединений, однако, если вас интересует доступ к базе данных, а не специально JDBC, вы можете посмотреть драйверы async db, такие как:

Эти драйверы полагаются на netty, поэтому все его операции ввода-вывода не блокируются, а это значит, что вам не нужно иметь пулы рабочих потоков. Меньше потоков означает меньшее переключение контекста на уровне ОС, что обеспечивает лучшую производительность.

К сожалению, таких драйверов не так много (я знаю только для MySQL и PostgreSQL), поэтому, если вы вынуждены работать с другими РСУБД, вам может быть не повезло.

0

vert.x предлагает с точки зрения запуска потоков на машине, а не с точки зрения пользователей.

Они говорят, что если у вас есть 16 ядер процессора и есть 16 готовых к работе потоков, то если вы выполняете операцию блокировки на 1 из них, то только 15 потоков остаются наиболее эффективными и, следовательно, только 15 из ваших ядер процессора на самом деле работают. 1 из ваших ядер просто ждет!

Поэтому, чтобы предотвратить наличие одного незанятого ядра, они советуют вам создать еще один поток и дать ему задачу блокировки, так что у вас все еще есть 16 потоков, работающих на ваших 16 ядрах процессора.

Количество блокирующих потоков не очень важно (до тех пор, пока оно не слишком велико...), поскольку они фактически не потребляют большую часть мощности вашего процессора.

Он отличается от обычной блокирующей модели, потому что вы изолировали операции блокировки, которые не требуют больших ресурсов на вашей стороне. Остается только обмен оставшимися событиями между рабочими потоками, которые у вас есть.

  • 0
    Хорошо, у меня все ясно, спасибо за ответ, но, как я уже говорил, если у вас 1000 пользователей, и все они должны выполнить операцию блокировки, так как это очень часто случается, вам нужно создать отдельный поток для каждого из них. пользователи, потому что каждому пользователю нужен собственный рабочий поток для запросов к базе данных (с JDBC). И тогда у вас будет 1000 открытых тем?
  • 0
    Да, но ничего не делать. Когда блокировка выполнена, их просто убивают или повторно используют для других пользователей, выполняющих блокировку ввода-вывода, как это делал бы CachedThreadPool.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню