2015-02-18 5 views
0

Я рассматриваю два подхода для отправки сообщений определенного типа по сети.Путь производительности Java против блокировки

1) Существует LoadBalancer с внутренним кешем, который имеет ссылку на каналы. Каждый канал имеет внутренний поток (вызываемый), который имеет реализацию для отправки сообщений и открытого интерфейса, на котором он принимает запросы sendMessage.

Канал предлагает метод LoadBalancer, на котором он может выполнять неблокирующую погоду запроса, он доступен для отправки другого сообщения.

Подводя итог: существует одна нить для LoadBalancer, которая непрерывно объединяет список каналов с чем-то вдоль линий isChannelReady() и отправляет другое сообщение, когда канал готов.

public class SomeLoadBalancingStrategy implements LoadBalancer { 
private List<Channel> channels = ChannelFactory.getChannels(//parameters here) 

// read from some queue 
while(there are messages) { 

foreach (channel) { 

// non blocking query 
if(channel.isReady()) { 

     channel.sendMessage(message) 
    } 
    } 
} 

2) Каждый объект канала представляет собой исполняемую нить, которая обертывает внутреннюю вызываемую ответственность за отправку сообщений. Каналы блокируются в некоторой параллельной очереди, ожидающей появления новых сообщений. Когда сообщение добавляется в очередь, канал runnable выбирает его и переходит к вызываемому. Этот runnable заблокирован в ожидании результата. Как только результат вызываемого доступен, обертка потока будет отображать следующее сообщение из очереди, возможно, через интерфейс LoadBalancer.

Итак, суммируем: есть два потока на канал, один из которых является вызываемым и отправляет сообщение, а второй ждет этого результата, чтобы он мог получить следующий запрос. В этом случае нет отдельных сообщений диспетчеризации потока LoadBalancer для каналов.

Некоторые примечания:

  • каналы используют синхронную связь с конечной точкой

  • Пожалуйста, обратите внимание мое объяснение решений только в качестве шаблона для базовых идей, которые я хотел бы обсудить

  • Там будет небольшое количество каналов, 5 не более

Будет ли второй подход всегда лучше работать? Существуют ли условия, при которых первый вариант был бы лучше? Аппаратное обеспечение, ОС, что-нибудь? Если каналы были асинхронными, изменилось бы это?

ответ

1

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

Это позволит добавить ненужное потребление ЦП. Я бы изменил 1), чтобы избежать этого, сохранив очередь блокировки «готовых» каналов. Балансировщик нагрузки вытащил готовый канал из очереди, и каналы добавили бы себя в очередь, когда они будут готовы к другому запросу.

В 2) Не видите, почему вам нужны два потока на канал, если это не навязывается внедрением операционного распределителя (API-интерфейса Callable?).

IMO оба варианта кажутся вполне эквивалентными по производительности, я не понимаю, почему один мог бы сделать намного лучше, чем другой; что 1) может гарантировать, что все каналы одинаково используются в циклическом фазировании, тогда как в 2), если есть низкий поток сообщений, существует вероятность того, что тот же канал всегда выполняет работу в зависимости от того, как виртуальная машина управляет коллекцией потоков Java, ожидающих появления нового элемента в очереди сообщений запроса.

+0

Да, думая об этом, нет необходимости иметь два потока на канал во втором варианте. Мне нравится ваше предложение блокировки очереди каналов, к которым подключаются каналы. Это также очень удобно, если один из каналов временно отключается. Спасибо за ваш ответ. – John

+0

Предполагая, что я использую блокирующую очередь каналов, как бы я вырвался из блокировки в такой очереди, если бы я хотел это сделать? Позволяет сказать, что я хочу делать это каждый раз так часто :) Я предполагаю добавить (и прочитать) какой-то специальный элемент, который указывает, что больше нет сообщений? – John

+0

@ user3360241 Не уверен, что вы имеете в виду. Я думаю, вы говорите о варианте 1. Почему бы вам не заблокировать балансировку нагрузки, если каналов больше нет (и пока некоторые не станут доступны)? Можете быть более конкретными? В противном случае это звучит так, будто вы возвращаетесь к интенсивному опросу ЦП, постоянно спрашивая, пока очередь готовых каналов не пуста, и я думаю, что это бесполезно, если не пустая трата циклов процессора. –

2

Будет ли второй подход всегда лучше работать с мудрым?

Невозможно сказать. Лучший вариант - проверить оба подхода. Обычно самое простое решение лучше всего, и добавление очереди перед очередью не всегда полезно (поток TCP - это очередь байтов)

Есть ли условия, при которых первый вариант был бы лучше?

Выделенные темы часто легче рассуждать и могут работать лучше. Это будет работать лучше, если у вас будет небольшое количество потоков.

Если каналы были асинхронными, это может иметь значение?

Да, но это невозможно сказать, если это будет лучше, но это будет сложнее.

Я предлагаю вам взглянуть на netty, если не использовать его, но изучить его подход.

+0

«Не могли бы вы прокомментировать: Выделенные темы часто легче рассуждать и могут работать лучше. Это будет работать лучше, если у вас будет небольшое количество потоков». В обоих случаях выделен поток на канал. Первый вариант, один для LoadBalancer и 1 на канал. Второй вариант, два на канал и 0 для LoadBalancer. – John

+0

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

+0

@ user3360241 Почему бы не просто по одному потоку на канал и добавить только потоки, если вы знаете, что вам это нужно? –

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