php - Как отключить пользователей API моего сайта?




linux apache (4)

Вы говорите, что «все лишние накладные расходы при каждом запросе будут побеждать цель», но я не уверен, что это правильно. Разве это не цель предотвращения взлома вашего сервера? Вероятно, это способ реализовать, так как это требует только быстрого чтения / записи. Вы даже можете обработать проверки сервера API на другой DB / диск, если вас беспокоит производительность.

Однако, если вы хотите альтернативы, вы должны проверить mod_cband , сторонний модуль apache, предназначенный для поддержки дросселирования полосы пропускания. Несмотря на то, что в основном это ограничение пропускной способности, он также может работать на основе запросов в секунду. Я никогда не использовал его, поэтому я не уверен, какие результаты вы получите. Был еще один модуль, называемый mod-throttle, но этот проект, похоже, сейчас закрыт и никогда не был выпущен для чего-либо выше серии Apache 1.3.

Легальные пользователи моего сайта иногда забивают сервер запросами API, которые вызывают нежелательные результаты. Я хочу установить ограничение не более, чем сказать один вызов API каждые 5 секунд или n вызовов в минуту (пока не определился с точным ограничением). Я мог бы зарегистрировать каждый вызов API в БД и выполнить расчет по каждому запросу, чтобы убедиться, что он превысил лимит, но все эти дополнительные накладные расходы при каждом запросе будут побеждать цель. Какие другие менее ресурсоемкие методы я мог бы использовать, чтобы установить лимит? Я использую PHP / Apache / Linux, для чего это стоит.


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

Хорошие новости: я сделал все это для вас: bandwidth-throttle/token-bucket

use bandwidthThrottle\tokenBucket\Rate;
use bandwidthThrottle\tokenBucket\TokenBucket;
use bandwidthThrottle\tokenBucket\storage\FileStorage;

$storage = new FileStorage(__DIR__ . "/api.bucket");
$rate    = new Rate(10, Rate::SECOND);
$bucket  = new TokenBucket(10, $rate, $storage);
$bucket->bootstrap(10);

if (!$bucket->consume(1, $seconds)) {
    http_response_code(429);
    header(sprintf("Retry-After: %d", floor($seconds)));
    exit();
}

Самое простое решение состоит в том, чтобы просто дать каждому ключу API ограниченное количество запросов в течение 24 часов и сбросить их в какое-то известное фиксированное время.

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

Таким образом, в их интересах будет не забивать вас запросами.


Я не знаю, жив ли этот поток или нет, но я бы предложил сохранить эти статистические данные в кеше памяти, например memcached. Это уменьшит накладные расходы на ведение журнала запроса в БД, но все еще будет служить цели.





throttle