2008-12-30 2 views
9

Я работаю над библиотекой Python, которая взаимодействует с API веб-сервисов. Как и многие веб-службы, с которыми я столкнулся, этот запрос требует ограничения скорости запросов. Я хотел бы предоставить необязательный параметр, limit, в экземпляр класса, который, если он предоставлен, будет содержать исходящие запросы до тех пор, пока не пройдет указанное количество секунд.Как ограничить скорость запросов к веб-сервисам в Python?

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

Это чехол для нарезания резьбы? Есть ли другой подход, который я не вижу?

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

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

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

Большое спасибо за ваши предложения!

Chris

ответ

6

Это работает лучше с очередью и диспетчером.

Вы разделили свою обработку на две части: источник и рассылка. Это могут быть отдельные потоки (или отдельные процессы, если это проще).

Источник сторона создает и запрашивает запросы при любой скорости, что делает их счастливыми.

Отправка сторона делает это.

  1. Получить запрос время запуска, s.

  2. Удаляет запрос, обрабатывает запрос через удаленную службу.

  3. Получить текущее время, t. Сон за курс - (t - s) секунд.

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

Сложная часть об этом создает некоторое представление для каждого запроса, который вы можете поставить в очередь. Поскольку Python Queue будет обрабатывать практически все, вам не нужно много делать.

Если вы используете многопроцессорную обработку, вам нужно будет pickle ваших объектов, чтобы поместить их в трубу.

1

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

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

И, наконец, похоже, что вы хотите быть компонентом промежуточного программного обеспечения. Не пытайтесь быть приложением и вводить темы самостоятельно. Просто блокируйте/спящий режим, если вы синхронны, и используйте инфраструктуру отправки async, если вы вызываетесь одним из них.

2

Очередь может быть чрезмерно сложной. Более простое решение - дать вашему классу переменную на время последнего вызова службы. Всякий раз, когда услуга вызывается (! 1), установите waitTime на delay - Now + lastcalltime. delay должно быть равно минимально допустимому времени между запросами. Если это число положительное, засыпайте это задолго до совершения звонка (! 2). Недостатком этого преимущества является то, что он обрабатывает запросы веб-сервисов как синхронные. Преимущество в том, что это абсурдно просто и легко реализовать.

  • (! 1): должно произойти сразу после получения ответа от службы внутри обертки (возможно, в нижней части обертки).
  • (! 2): должно произойти, когда оболочка python вокруг веб-службы вызывается в верхней части обертки.

Решение S.Lott более элегантно, конечно.

1

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

Я использую twisted для взаимодействия практически со всеми в наше время. Это упрощает выполнение этого типа, имея модель, которая отделяет представление запроса от обработки ответа. Если вы не хотите, чтобы ваши пользователи API могли использовать скрученные, вам, по крайней мере, было бы лучше понять их API для отложенного исполнения.

Например, у меня есть интерфейс twitter, который отталкивает довольно абсурдное количество запросов от имени xmpp users. Я не оцениваю ограничение, но мне пришлось немного потрудиться, чтобы все запросы не возникали одновременно.

0

SO Я предполагаю, что-то простое, как времени импорта time.sleep (2) не будет работать для ожидания 2 секунды между запросами

+0

Bad предположения. Он ждет 2 секунды.Это будет 2 секунды. между концом одного и началом другого. Обычно вы хотите 2 сек. между началом одного и началом другого. –

+0

Ну, ожидание двух секунд между окончанием одного и началом другого может быть более безопасным, если лимиты выполняются на основе фактического времени между вызовами. Реальная проблема заключается в том, что ваше решение ожидает более двух секунд между запросами, поскольку для вычисления между запросами может потребоваться время. – Brian

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

  • Нет связанных вопросов^_^