Python: штраф за потоки сна

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

Фон: Я реализую магазин онлайн с помощью django/satchmo. Требование для отстроченной уплаты. Клиент может зарезервировать продукт и позволить третьему лицу платить за него позднее (через случайный и уникальный URL).

Для обработки нерезервирования объекта, я создаю поток, который будет спать в течение времени резервирования и затем удалять резервирование/метку продукт, как продано, когда это проснется. Это похоже на это:

#Reserves a product when it is placed in the cart
def reserve_cart_product(product):
  log.debug("Reserving %s" % product.name)
  product.active = False
  product.featured = False
  product.save()
  from threading import Timer
  Timer(CART_RESERVE_TIME, check_reservation, (product,)).start()

Я использую ту же технику при отборе уникальных URL после того, как они истекли, только сны Таймера для намного дольше (обычно 5 дней).

Так, мой вопрос Вам ТАК следующие:

Имеет большой numnber потоков сна собирающийся серьезно производить производительность? Есть ли лучшие методы для планирования того от события когда-то в будущем. Я хотел бы сохранить это в Python если возможным; никакой вызов at или cron через sys.

Сайт не является точно интенсивным трафиком; (щедрый) верхний предел продуктов, заказанных в неделю, был бы приблизительно 100. Объединенный с резервированием корзины, это могло означать, что существует 100 + спящие потоки в любой момент. Я буду сожалеть, что планировал задачи этим способом?

Спасибо

7
задан pisswillis 1 February 2010 в 17:09
поделиться

3 ответа

Я не вижу причин, по которым это не должно работать. Базовый код для Timer (в threading.py) просто использует time.sleep. После некоторого ожидания он в основном запускает цикл с time.sleep (0,05). Это должно привести к загрузке ЦП практически на 0%, даже с сотнями потоков. Вот простой пример, в котором я заметил, что процесс python используется на 0%:

import threading

def nothing():
    pass

def testThreads():
    timers = [threading.Timer(10.0, nothing) for _ in xrange(881)]
    print "Starting threads."
    map(threading.Thread.start, timers)
    print "Joining threads."
    map(threading.Thread.join, timers)
    print "Done."

if __name__ == "__main__":
    testThreads()

Настоящая проблема в том, что вы не сможете запустить слишком много потоков. В моей 64-битной системе 4 ГБ я могу запустить только 881 поток, прежде чем я получу сообщение об ошибке. Если у вас действительно будет всего несколько сотен, я не могу представить, что это не сработает.

7
ответ дан 6 December 2019 в 15:22
поделиться

Обычно спальные нити не имеют верхних расходов от памяти, выделенной для их стеков и других личных данных. Современные алгоритмы планирования операционной системы имеют сложность O (1), поэтому даже бегущая нить не вносит накладные расходы, кроме следа памяти. В то же время трудно представить эффективный дизайн, требующий многих нитей. Только случай, когда я могу представить, это общение со многими другими сверстниками. В этом случае - асинхронный IO должен быть использован.

3
ответ дан 6 December 2019 в 15:22
поделиться

100 потоков - это не проблема, но, как указал tgray , что произойдет, если сервер выйдет из строя (отключение питания, плановое обслуживание, отказ оборудования и т. Д.)?

Вам необходимо сохранить информация о несохранении где-то в вашей базе данных.

Тогда у вас может быть задание cron, которое периодически запускает скрипт снятия резервирования, например, и вам не нужно, чтобы все эти потоки сидели без дела.

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

4
ответ дан 6 December 2019 в 15:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: