Рекомендации по проектированию ограничителя скорости запроса API?

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

PHP

Здесь я рассмотрел вопрос о переносе переменной bucket в кеш APCu, но я не совсем уверен, как это потокобезопасно. Я представляю себе сценарий: в ковше остается один токен. Клиент A вытаскивает данные из кеша, а затем клиент B сразу после. Заметки есть один левый и вычитает токен, тогда B делает то же самое, ведро находится в -1, и оба считают, что они понятны для запроса. Если кучка нитей это делает, я нарушаю предел. Это реалистичный сценарий? Есть ли лучший способ реализовать этот предел API на основе всего сайта (не для каждого пользователя)? Я бы предпочел не прибегать к внешнему скрипту.

node.js

Узел кажется, что это было бы прекрасно, учитывая архитектуру сайта, но это огромный сдвиг в мышлении. У этого есть только один поток исполнения, и есть также глобальные вары, которые, как говорят документы, являются локальными для модуля. Я предполагаю, что «локальный для модуля» означает его доступный только для этого модуля, но «глобальный» означает, что всякий раз, когда один модуль появляется в очереди событий, там будет глобальный var. Это так? Если это так, когда ведро пустое, и модуль должен ждать, чтобы поместить запрос, который блокирует все, что делает узел, не так ли? И если запущено несколько экземпляров node.js, глобальное не разделяется между ними, не так ли? Я видел несколько пакетов npm для ограничения скорости, но все они кажутся для каждого пользователя.

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

Любые советы?

7 голосов | спросил TseehnMarhn 18 FriEurope/Moscow2015-12-18T02:16:10+03:00Europe/Moscow12bEurope/MoscowFri, 18 Dec 2015 02:16:10 +0300 2015, 02:16:10

2 ответа


1

PHP

Ваше чтение /запись в кеше - это критический раздел . Вам необходимо защитить его, выбрав взаимное исключение , чтобы предотвратить ложное прочитайте, что вы описали. К лучшему или худшему, блокировка в PHP не проста. Кросс-платформенное решение использует файл (гарантированный для того, чтобы вызвать горе, если ваш сервер занят). Кроме того, это зависит как от конфигурации ОС, так и от сервера. Вы можете прочитать здесь: https://stackoverflow.com/a/2921596/7625 .

Node.js

Поскольку Node является однопоточным, вам не нужна блокировка, если вы не выполняете операцию async (I /O и связанные с ней). Однако это не обязательно решает все ваши проблемы. Подробнее см. Ниже.

Все

Как описано, у вас возникла большая проблема. Я вижу догадку, когда вы говорите: «... это заблокирует все, что делает узел, не так ли?» Это не точная проблема - вы можете создать неблокирующее ожидание. Но ждет ли решение ваших проблем? На самом деле, нет. Если ваш сайт действительно занят, каждый запрос ожидания увеличивает вероятность того, что следующий запрос будет ждать. Запросы накапливаются ... Если есть достаточно трафика, ожидания будут длиннее и длиннее. Там будут таймауты. Там будет ручная работа. Будут слезы.

Это проблема с равными возможностями. Ни PHP, ни Node не защищены. (На самом деле, все уязвимы, учитывая дросселируемый ресурс и описанный вами подход.) Очередь сообщений не спасает вас. Вся очередь сообщений вызывает вас в очереди запросов в очереди ожидания . Нам нужен способ отменить эти запросы!

К счастью, это может быть довольно прямолинейно, если мы будем больше доверять браузеру. С небольшим повторным смещением ответ обратно в браузер может содержать статус и необязательный результат. На сервере отправьте статус «успех» и результат, если вы получите токен API. В противном случае отправьте статус «еще не». В браузере, если запрос успешно выполняется, как обычно. Если нет, действуйте так, как считаете нужным. Если вы отправляете запросы асинхронно, вы можете повторить попытку через полсекунды, затем полную секунду, затем ... Есть большие возможности для предоставления обратной связи с пользователем. Помимо отличной обратной связи, этот подход также сдерживает серверные ресурсы. Сервер не будет наказан за узкое место стороннего API.

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

Откройте свой кошелек

Я предполагаю, что ваш сторонний API дросселирован, потому что он бесплатный! (или недорогой). Если вы действительно хотите, чтобы ваши пользователи стали ваять, подумайте о том, чтобы платить за лучший сервис. Вместо того, чтобы конструировать свой выход из проблемы (что довольно круто, sorta chintzy), исправить проблему наличными. Помните, что многие, многие операции, которые бегут по дешевке, чувствуют себя дешево. Если вы хотите сохранить своих пользователей, вы не хотите этого.

ответил Scant Roger 20 SunEurope/Moscow2015-12-20T01:31:19+03:00Europe/Moscow12bEurope/MoscowSun, 20 Dec 2015 01:31:19 +0300 2015, 01:31:19
-1

.net имеет класс SemaphoreSlim для такого типа вещей, вы можете использовать шаблон singleton, чтобы сделать его глобальным. ConcurrentQueue и другие объекты также могут помочь.

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

Я бы порекомендовал вам взглянуть на фреймворки очереди сообщений, такие как msmq, rabbit, zeroMq и т. д., чтобы помочь с общей архитектурой.

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

Эти рабочие приложения не подходят для веб-хостинга, таких как IIS, PHP или NodeJS. Я бы предложил услугу Windows. (но тогда im .net) кажется, что демон unix является equivilant в СССР, и вы можете использовать его для создания:  ( https://www.digitalocean.com/community/tutorials/how-to-write-a-linux-daemon-with-node-js-on-a-vps )

также см. этот вопрос, почему это трудно сделать в JS

https://stackoverflow.com/questions/555191/javascript-semaphore-test и-набор антиблокировочной

Однако PHP имеет реализацию семафора

http://php.net/manual/en/intro.sem.php

ответил Ewan 19 SatEurope/Moscow2015-12-19T17:09:19+03:00Europe/Moscow12bEurope/MoscowSat, 19 Dec 2015 17:09:19 +0300 2015, 17:09:19

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132