Как ограничить число запросов к веб-службам в Python?
Я работаю над библиотекой Python, которая взаимодействует с API веб-службы. Как и многие веб-службы, с которыми я сталкивался, этот запрос ограничивает скорость запросов. Я хотел бы предоставить необязательный параметр,limit
, к экземпляру класса, который, если это предусмотрено, будет удерживать исходящие запросы до тех пор, пока не пройдет указанное количество секунд.
Я понимаю, что общий сценарий следующий: экземпляр класса делает запрос с помощью метода. Когда это происходит, метод испускает некоторый сигнал, который устанавливает переменную блокировки где-то и начинает таймер обратного отсчета для количества секунд в limit
. (По всей вероятности, блокировка-это сам таймер обратного отсчета.) Если другой запрос был сделан в течение этого времени, она должна быть отложена, пока обратный отсчет таймера достигнет нуля и блокировка снимается; на данный момент, старейший заявку на очереди и таймер сбрасывается и замок снова обручились.
это случай для резьбы? Есть есть другой подход, который я не вижу?
должен ли таймер обратного отсчета и блокировка быть переменными экземпляра или они должны принадлежать классу, чтобы все экземпляры класса удерживали запросы?
кроме того, это вообще плохая идея предоставить функциональность ограничения скорости в библиотеке? Поскольку по умолчанию отсчет времени равен нулю секунд, библиотека по-прежнему позволяет разработчикам использовать библиотеку и предоставлять свои собственные схемы ограничения скорости. Учитывая любые разработчики, использующие служба в любом случае должна будет ограничивать запросы на ограничение скорости, однако я полагаю, что библиотеке было бы удобно предоставить средство ограничения скорости.
независимо от размещения схемы ограничения скорости в библиотеке или нет, я хочу написать приложение с использованием библиотеки, поэтому предлагаемые методы пригодятся.
большое спасибо за ваши предложения!
Крис
6 ответов
Это работает лучше с очередью и диспетчер.
вы разделяете обработку на две стороны:источник и отправка. Это могут быть отдельные потоки (или отдельные процессы, если так проще).
на источник сторона создает и запрашивает запросы с любой скоростью, что делает их счастливыми.
на отправка сторона это делает.
получить время начала запроса, s.
извлекает запрос, обрабатывает запрос через дистанционное обслуживание.
получить текущее время, t. Спать скорость - (t -s) секунд.
Если вы хотите запустить источник сторона, подключенная непосредственно к удаленной службе, вы можете сделать это и ограничить скорость обхода. Это хорошо для внутреннего тестирования с макетной версией удаленной службы.
трудная часть об этом-создание некоторого представления для каждого запроса, который вы можете запросить. Поскольку в Python очереди будет обрабатывать почти все, вам не нужно много делать.
Если вы используете мульти-обработку, вам придется огурец ваши объекты, чтобы положить их в трубу.
очередь может быть слишком сложной. Более простое решение-дать вашему классу переменную на время последнего вызова службы. Всякий раз, когда служба вызывается (!1), набор waitTime к delay - Now + lastcalltime
. delay
должно быть равно минимально допустимому времени между запросами. Если этот номер положительный, спите долго, прежде чем звонить (!2). Недостатком / преимуществом этого подхода является то, что он рассматривает запросы веб-службы как синхронные. Преимущество в том, что это абсурдно просто и легко реализовать.
- (!1): должно произойти сразу после получения ответа от службы, внутри обертки (возможно, в нижней части обертки).
- (!2): должно произойти, когда оболочка python вокруг веб-службы вызывается в верхней части оболочки.
решение S. Лотта более элегантно, конечно.
на вашу схему ограничения скорости должно сильно влиять соглашение о вызовах базового кода (syncronous или async), а также Какая область (поток, процесс, машина, кластер?) это ограничение скорости будет действовать.
Я бы предложил сохранить все переменные в экземпляре, чтобы вы могли легко реализовать несколько периодов / скоростей управления.
наконец, похоже, что вы хотите быть компонентом промежуточного программного обеспечения. Не пытайтесь быть приложением и вводите темы самостоятельно. Просто блокируйте / спите, Если вы синхронны и используете async dispatching framework, если вы вызываетесь одним из них.
Если ваша библиотека предназначена для синхронной работы, я бы рекомендовал исключить ограничение (хотя вы могли бы отслеживать ставки и, по крайней мере, помочь вызывающему абоненту решить, как соблюдать ограничения).
Я использую twisted для взаимодействия практически со всем в настоящее время. Это позволяет легко делать такие вещи, имея модель, которая отделяет представление запроса от обработки ответа. Если вы не хотите, чтобы ваши пользователи API использовали twisted, вы по крайней мере лучше понять их API для отложенного выполнения.
например, у меня есть интерфейс twitter, который проталкивает довольно абсурдное количество запросов от имени пользователи xmpp. Я не ставлю предел, но мне пришлось немного поработать, чтобы предотвратить все запросы одновременно.
Так что я предполагаю что-то простое, как время импорта время.сон(2) работать не будет ждать 2 секунды между запросами
Не изобретайте колесо, если это не требуется. Проверьте эту удивительную библиотеку -[ratelimit][1]
. Идеально, если вы просто хотите, чтобы оценить ограничить свои звонки в REST api по какой-либо причине и продолжить свою жизнь.