Фон
Echo Nest имеет ограниченный скоростью API. Данное приложение (идентифицированное в запросах с использованием ключа API) может составлять до 120 вызовов REST в минуту. Ответ службы включает оценку общего количества вызовов, сделанных в последнюю минуту; повторное злоупотребление API (превышение лимита) может привести к отзыву ключа API.
При использовании с одной машины (веб-сервера, предоставляющего услугу клиентам), легко контролировать доступ - сервер имеет полное знание истории запросов и может правильно регулировать себя.
Но я работаю над программой, в которой распределенные, независимые клиенты делают запросы параллельно.
В таком случае гораздо менее понятно, каким будет оптимальное решение. И вообще проблема кажется неразрешимой - если более 120 клиентов, все из которых не имеют предыдущей истории, одновременно создают первоначальный запрос, тогда скорость будет превышена.
Но так как это персональный проект, и ожидается, что использование клиента будет спорадическим (всплеск), и мои проекты никогда не были чрезвычайно успешными, и это, как ожидается, не будет большой проблемой. Более вероятная проблема заключается в том, что бывают случаи, когда меньшее количество клиентов хочет как можно быстрее сделать много запросов (например, клиенту может потребоваться, в исключительных случаях, сделать несколько тысяч запросов при запуске в первый раз - возможно два клиента начнут примерно в одно и то же время, поэтому они должны сотрудничать, чтобы предоставить доступную пропускную способность).
Учитывая все вышеперечисленное, какие подходящие алгоритмы для клиентов, чтобы они соответствовали требованиям к скорости? Обратите внимание, что ограниченное сотрудничество возможно, потому что API возвращает общее количество запросов в последнюю минуту для всех клиентов.
Текущее решение
Мое текущее решение (когда вопрос был написан - лучший подход дается как ответ) довольно просто. Каждый клиент имеет запись о времени последнего звонка и количестве вызовов, сделанных в последнюю минуту, как сообщается API, по этому вызову.
Если количество вызовов меньше 60 (половина предела), клиент не дросселирует. Это позволяет получать быстрые пакеты с небольшим количеством запросов.
В противном случае (т.е. когда есть больше предыдущих запросов) клиент вычисляет предельную скорость, в которой он должен работать (т.е. period = 60 / (120 - number of previous requests)
), а затем ждет, пока разрыв между предыдущим вызовом и текущим временем не превысит этот период (в секунд, 60 секунд в минуту, 120 максимальных запросов в минуту). Это эффективно дросселирует скорость так, чтобы, если бы она действовала одна, она не превышала бы предела.
Но вышеизложенное имеет проблемы. Если вы тщательно продумываете это, вы увидите, что для большого количества запросов один клиент колеблется и не достигает максимальной пропускной способности (это отчасти из-за "начального всплеска", который внезапно "выпадет за окно", а отчасти потому, что алгоритм не в полной мере использует свою историю). И несколько клиентов будут сотрудничать до некоторой степени, но я сомневаюсь, что это оптимально.
Лучшие решения
Я могу представить лучшее решение, которое использует полную локальную историю клиента и моделирует других клиентов, скажем, с помощью скрытой марковской модели. Таким образом, каждый клиент будет использовать отчет API для моделирования других (неизвестных) клиентов и соответственно корректировать его.
Я также могу представить алгоритм для одного клиента, который постепенно переходит от неограниченного поведения для небольших всплесков к оптимальному, ограниченному поведению для многих запросов без введения колебаний.
Существуют ли такие подходы? Может ли кто-либо предоставить реализацию или ссылку? Может ли кто-нибудь подумать о лучшей эвристике?
Я предполагаю, что это известная проблема где-то. В какой области? Теория очередей?
Я также предполагаю (см. комментарии ранее), что нет оптимального решения и что может существовать некоторая практика/традиция/принятая эвристика, которая хорошо работает на практике. Я хотел бы знать, что... На данный момент я изо всех сил пытаюсь идентифицировать подобную проблему в известных сетевых протоколах (я полагаю, что у Perlman было бы какое-то красивое решение, если бы так).
Мне также интересно (в меньшей степени, для дальнейшего использования, если программа становится популярной) в решении, для которого требуется центральный сервер для совместной работы.
Отказ
Этот вопрос не предназначен для критики Эхо-Гнезда вообще; их обслуживание и условия использования велики. Но чем больше я думаю о том, как лучше всего использовать это, тем сложнее/интереснее это становится...
Кроме того, каждый клиент имеет локальный кеш, используемый для предотвращения повторных вызовов.