Я пытаюсь сделать тысячи запросов GET за минимально возможное время. Мне нужно сделать это масштабируемым способом: удвоение количества серверов, которые я использую для выполнения запросов, должно вдвое сократить время выполнения для фиксированного количества URL-адресов.
Я использую Celery с пулом событий и RabbitMQ в качестве брокера. Я создаю один рабочий процесс на каждом рабочем сервере с помощью --concurrency 100
и имею выделенный главный сервер, выдающий задачи (код ниже). Я не получаю ожидаемых результатов: время выполнения совсем не сокращается при удвоении числа используемых рабочих серверов.
Похоже, что по мере того, как я добавляю больше рабочих серверов, использование каждого рабочего сервера снижается (как сообщает Flower). Например, с 2 рабочими потоками во время выполнения количество активных потоков на одного рабочего колеблется в диапазоне от 80 до 90 (как и ожидалось, поскольку параллелизм равен 100). Однако при 6 рабочих потоках количество активных потоков на одного рабочего колеблется в диапазоне от 10 до 20.
Это похоже на то, что размер очереди слишком мал, или рабочие серверы не могут достаточно быстро вытаскивать задачи из очереди, чтобы их можно было полностью использовать, и по мере того, как вы добавляете больше рабочих, им становится все труднее быстро вытаскивать задачи из очереди.
urls = ["https://...", ..., "https://..."]
tasks = []
num = 0
for url in urls:
num = num + 1
tasks.append(fetch_url.s(num, url))
job = group(tasks)
start = time.time()
res = job.apply_async()
res.join()
print time.time() - start
Обновление: я приложил график успешно выполненных задач в зависимости от времени при использовании 1 рабочего сервера, 2 рабочих серверов и т. д. до 5 рабочих серверов. Как видите, скорость выполнения задачи удваивается при переходе от 1 рабочего сервера к 2 рабочим серверам, но по мере добавления дополнительных серверов скорость выполнения задачи начинает выравниваться.
eventlet.sleep(0.2)
. Во-вторых, попробуйте получить доступ к целевому сервису через небезопасный http, недавно была исправлена соответствующая ошибка в eventlet. В-третьих, избавиться от rabbitmq, ненавижу это говорить, всегда хорошая идея, брокер Redis работает лучше. И, наконец, предлагаю избавиться от celery, если вам приходится обрабатывать каждый запрос по отдельности. В противном случае группируйте запросы и отправляйте в очередь небольшими партиями, это определенно поможет решить проблему с производительностью очереди (если она есть). - person temoto   schedule 08.02.2018