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

При создании объекта RealThreadPool Executor в Java вам необходимо передать аргумент, описывающий количество потоков, которые Исполнитель может выполнять одновременно. Я строю класс обслуживания, ответственным за обработку больших наборов телефонных номеров. Для каждого номера телефона мне нужно выполнить веб-сервис (это мое узкое место), а затем сохранить ответ в хэш-карте.

Чтобы сделать это узкое место менее вредным для производительности моего сервиса, я решил создать класс Worker, который извлекает необработанные элементы и обрабатывает их. Рабочий класс реализует интерфейс Runnable, и я запускаю Workers с помощью Executor.

Число рабочих, которые могут запускаться в одно и то же время, зависит от размера Executor FixedThreadPool. Каков безопасный размер для ThreadPool? Что может произойти, когда я создаю FixedTheradPool с некоторым большим числом в качестве аргумента?

Ответы

Ответ 1

Если каждому рабочему потоку необходимо выполнить вызов веб-службы, то количество потоков в вашем пуле должно сильно зависеть от того, сколько одновременных запросов может обрабатывать ваш веб-сервис. Больше нитей, чем это, не будет ничего, кроме подавления веб-службы.

Ответ 2

Что-то, что можно было бы рассмотреть, это смотреть

Runtime.getRuntime().availableProcessors()

который дает некоторое направление в отношении того, сколько потоков будет иметь смысл для системы.

Ответ 3

Я где-то читал, что оптимальное количество потоков - это число ядер * 25. Похоже, что .NET использует это по умолчанию для ThreadPool. Однако, если у вас много вызовов веб-сервисов, вам лучше использовать один поток и проверить список вызовов веб-служб для ответа. Когда ответ пришел, просто обработайте запись и удалите ее из списка.

Ответ 4

Если у вас есть доступ к веб-службе, попробуйте создать пакетную функцию для проверки нескольких телефонных номеров при одном вызове.

В новой .NET есть ThreadPool, который может расти и сокращаться на основе собственного профиля производительности. К сожалению, версия Java либо исправлена, либо возрастает до предела, основанного на поступающей работе.

У нас были такие же проблемы. Наше решение заключалось в том, чтобы позволить клиенту увеличить размер пула и настроить производительность по своему усмотрению.

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

Ответ 5

Если каждое вычисление эквивалентно вызову веб-службы, тогда вы должны подумать о том, сколько нагрузки вы добавляете в эту службу/сколько параллельных подключений, которые служба будет терпеть или будет разрешена владельцами услуг. Большинство общедоступных служб будут ожидать только одного такого подключения от одного пользователя за раз. Если возможно, обратитесь к владельцам услуг за их политикой использования. Количество таких соединений определит количество потоков, которые вы можете использовать.

Ответ 6

Предположим, что веб-служба бесконечно масштабируема и что никто не заботится о том, чтобы вы отправляли спам с запросами. Предположим также, что ответы веб-службы находятся в диапазоне 1 секунду, тогда как время локальной обработки составляет 5 миллисекунд.

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

В этих предположениях вы не сможете увеличить пропускную способность многоядерного процессора для любого разумного размера пула потоков. Для достижения максимальной транзакции в секунду вам нужно разбить поток на модель подключения. Посмотрите на неблокирующий I/O (NIO), упомянутый ранее, или на реализацию Java для асинхронного образца тонов завершения (IO Completion в Windows).

Обратите внимание, что память стека, зарезервированная для каждого созданного потока, фактически является просто зарезервированным адресным пространством, а не фактической выделенной или зафиксированной памятью. По мере того, как стек пытается расти, генерируются исключения, которые приводят к тому, что память стека становится обязательной по требованию. Следствием этого является то, что это действительно актуально только для 32-разрядных менеджеров памяти. Для 64-разрядной памяти у вас огромное адресное пространство, хотя вы только возвращаете небольшую часть этого пространства с физической памятью. По крайней мере, так я понимаю, что работает Windows, я не уверен в мире Unix.

Ответ 7

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

Этот размер стека настраивается через -Xss (аналогично -Xmx и т.д.). Я считаю, что по умолчанию 512 Кбит на поток. На данный момент я не могу найти авторитетных, чтобы подтвердить это.

Ответ 8

Интересно, лучше ли вам использовать NIO, а не потоки, поскольку ваш ограничивающий фактор будет сервером веб-сервисов и узким местом сети, а не клиентом.

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

Ответ 9

Если вы делаете тяжелые вычисления, говорите, что для параллельных манипуляций с массивами тогда правило имеет число потоков для количества процессоров.