2014-03-14 3 views
1

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

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

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

И вот, когда мы пришли на мой вопрос:

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

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

ответ

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

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

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

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

Число блокирующих потоков не имеет особого значения (если оно не слишком велико ...), поскольку они фактически не потребляют большую часть мощности вашего ЦП.

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

+0

ОК У меня это ясно, спасибо за ответ, но, как я уже говорил, если у вас 1000 пользователей, и все они должны выполнять операцию блокировки, так как это очень часто бывает, вам нужно создать отдельную нить для каждый из этих пользователей приводит к тому, что каждый пользователь нуждается в собственном рабочем потоке для запроса базы данных (с JDBC). И тогда у вас в итоге есть 1000 открытых потоков? – javalava

+0

Да, но ничего не делая. Когда блокировка завершена, они просто убиты или повторно используются для других пользователей, блокирующих IO, как это делает CachedThreadPool. –

+0

Не забудьте ограничить соединения JDBC в пуле подключений. –

0

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

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

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

0

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

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

Смежные вопросы