rate limit exceeded что делать

Ошибка в товаре (Ошибка. Rate limit exceeded Запрошенный ресурс недоступен.) Есть решение

На страницах некоторых товаров. в место товара выдает вот такой текст:

Подскажите с чем связана такая ошибка?

И как с ней бороться?

8 ответов

Видимо у вас какой-то плагин что-то запрашивает с удаленного сервера. Twitter? Отзывы ЯМаркет? Карты?

В общем многие сервисы ограничивают число запросов к их API определенным числом в сутки или в час.

У твиттера есть лимит по времени. Поэтому он выдает такое сообщение об ошибке. А плагин выводит это сообщение. Ни на чем это не сказывается, кроме как на возможности отправлять в твиттер. Нужно подождать минут 5-10 и эта надпись исчезнет.

Ой. Что-то я засомневался. Мой плагин твиттера выдаст просто:

Он не спрячет товар и не напишет «Запрошенный ресурс недоступен». Возможно это что-то другое.

Оказался модуль загрузки отзывов с Яндекс Маркета.

А какой именно плагин?

Просто у меня тоже есть такой, но я там, вроде, устанавливал лимит на время подключения.

Количество обращений к Контентному API Яндекса по базовому, бесплатному тарфиу — 100 запросов в сутки https://tech.yandex.ru/market/content-data/

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

Добавить ответ

Webasyst — это CMS нового поколения, совмещающая в себе инструменты для управления сайтом и интернет-магазином с полезными приложениями для совместной работы с коллегами и взаимодействия с клиентами. Единый центр управления бизнесом через интернет.

Платформа
Магазин Webasyst
Помощь

Мы получаем и обрабатываем персональные данные посетителей сайта в соответствии с Политикой обработки персональных данных. Отправка персональных данных с помощью любой страницы сайта подразумевает согласие со всеми пунктами Политики.

Источник

Ограничиваем скорость на маршрутизаторе Cisco. Технология rate-limit

Rate-limit команда вводится в режиме конфигурирования физического интерфейса и имеет следующий синтаксис:

rate-limit input|output [access-group [rate-limit] acl-index] [limit-bps] [nbc] [ebc] conform-action [action] exceed-action [action]

Далее идут три значения скорости limit bps, nbc, ebc

Для расчета всех значений используем такую формулу:

Теперь давайте посмотрим на практике. Возьмем GNS3, один маршрутизатор и две виртуальные машины.
rate limit exceeded что делать. Смотреть фото rate limit exceeded что делать. Смотреть картинку rate limit exceeded что делать. Картинка про rate limit exceeded что делать. Фото rate limit exceeded что делать

Топология простейшая, чтобы просто показать как это работает.

Ограничим весь трафик из сети 192.168.40.0/24 в сеть 192.168.78.0/24. Для этого на R1 создаем ACL.

Ограничиваем абсолютно весь трафик. Пример простой, могут быть более сложные ACL, чтоб ограничивать скорость по каким-то сервисам, портам и пр.

Проверим скорость в сети до ограничений.

На хосте C1 у нас работает FTP-сервер, С2 — будет ftp-клиентом. Скорость виртуальной сети у меня 1Мбит/c
rate limit exceeded что делать. Смотреть фото rate limit exceeded что делать. Смотреть картинку rate limit exceeded что делать. Картинка про rate limit exceeded что делать. Фото rate limit exceeded что делать

Видим что скорость закачки около 1Мбит/c.

После этого вешаем на физический интерфейс rate-limit, который смотрит в сеть 192.168.40.0/24

Теперь мы ограничили скорость до 8Кбайт/сек. Проверяем.
rate limit exceeded что делать. Смотреть фото rate limit exceeded что делать. Смотреть картинку rate limit exceeded что делать. Картинка про rate limit exceeded что делать. Фото rate limit exceeded что делать

Источник

Error: Rate Limit Exceeded #145

Comments

starleaf1 commented May 18, 2017

I encounter the following exception when I try to sync using the grive command

The text was updated successfully, but these errors were encountered:

skydivingpt commented May 25, 2017 •

Failed to obtain auth token: HTTP 400, body: <
«error» : «invalid_grant»
>
exception: /build/grive2-2Hxkkx/grive2-0.5.1/libgrive/src/protocol/OAuth2.cc(80): Throw in function void gr::OAuth2::Auth(const string&)
Dynamic exception type: boost::exception_detail::clone_implgr::OAuth2::AuthFailed
[gr::expt::BacktraceTag*] = #0 0x578d79 grive gr::Exception::Exception()
#1 0x5651a7 grive gr::OAuth2::AuthFailed::AuthFailed()
#2 0x564271 grive gr::OAuth2::Auth(std::__cxx11::basic_string const&)
#3 0x50b576 grive Main(int, char**)
#4 0x50c1e9 grive main
#5 0x7f7d3ba2f830 /lib/x86_64-linux-gnu/libc.so.6 __libc_start_main
#6 0x50a4b9 grive _start

konradsa commented Aug 1, 2017

exception: /home/pi/git/grive2/libgrive/src/protocol/AuthAgent.cc(159): Throw in function long int gr::AuthAgent::CheckHttpResponse(long int, const string&, const gr::http::Header&)
Dynamic exception type: N5boost16exception_detail10clone_implIN2gr4http5ErrorEEE
[PN2gr4expt12BacktraceTagE] = #0 0x14dabc :0 gr::Exception::Exception()
#1 0x123380 :0 gr::http::Error::Error()
#2 0x12b480 :0 gr::AuthAgent::CheckHttpResponse(long, std::string const&, gr::http::Header const&)
#3 0x12b024 :0 gr::AuthAgent::Request(std::string const&, std::string const&, gr::SeekStream*, gr::DataStream*, gr::http::Header const&, unsigned long long)
#4 0x121840 :0 gr::http::Agent::Get(std::string const&, gr::DataStream*, gr::http::Header const&, unsigned long long)
#5 0x16dbe8 :0 gr::v2::Feed2::GetNext(gr::http::Agent*)
#6 0x1099a8 :0 gr::Drive::DetectChanges()
#7 0xe5b1c :0 Main(int, char**)
#8 0xe62a4 :0 main
#9 0x7684f294 /lib/arm-linux-gnueabihf/libc.so.6 __libc_start_main

[PN2gr4http15ResponseBodyTagE] = <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>

gmyuriy commented Aug 16, 2017

Same here. At least can you make it fail gracefully and repeat failed request?

exception: /build/grive2-2Hxkkx/grive2-0.5.1/libgrive/src/protocol/AuthAgent.cc(159): Throw in function long int gr::AuthAgent::CheckHttpResponse(long int, const string&, const gr::http::Header&)
Dynamic exception type: boost::exception_detail::clone_implgr::http::Error
[gr::expt::BacktraceTag*] = #0 0x578d79 grive gr::Exception::Exception()
#1 0x5597d7 grive gr::http::Error::Error()
#2 0x56119c grive gr::AuthAgent::CheckHttpResponse(long, std::__cxx11::basic_string const&, gr::http::Header const&)
#3 0x560c02 grive gr::AuthAgent::Request(std::__cxx11::basic_string const&, std::__cxx11::basic_string const&, gr::SeekStream*, gr::DataStream*, gr::http::Header const&, unsigned long long)
#4 0x560560 grive gr::http::Agent::Get(std::__cxx11::basic_string const&, gr::DataStream*, gr::http::Header const&, unsigned long long)
#5 0x556dd8 grive gr::v2::Feed2::GetNext(gr::http::Agent*)
#6 0x5442a9 grive gr::Drive::DetectChanges()
#7 0x50b9da grive Main(int, char**)
#8 0x50c1e9 grive main
#9 0x7fe401449830 /lib/x86_64-linux-gnu/libc.so.6 __libc_start_main
#10 0x50a4b9 grive _start

[gr::http::ResponseBodyTag*] = <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>

[gr::http::ResponseCodeTag*] = 403
[gr::http::RequestHeadersTag*] = Authorization: Bearer
GData-Version: 3.0

[gr::http::ResponseHeadersTag*] = HTTP/1.1 403 Forbidden
Vary: X-Origin
Content-Type: application/json; charset=UTF-8
Date: Wed, 16 Aug 2017 05:30:12 GMT
Expires: Wed, 16 Aug 2017 05:30:12 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Alt-Svc: quic=»:443″; ma=2592000; v=»39,38,37,35″
Accept-Ranges: none
Vary: Origin,Accept-Encoding
Transfer-Encoding: chunked

bebo-dot-dev commented Sep 23, 2017

I see the same issue here occasionally. For me I believe it coincides with having performed some large maintenance task on my google drive i.e. deleting thousands of files / emptying the bin via the drive web app / drive android app. https://developers.google.com/drive/v3/web/handle-errors#403_rate_limit_exceeded

kigiri commented Feb 4, 2018

Same here, I delete a somewhat big folder

3000 files of 5mb each and now the sync fail with 403 Rate Limit Exceeded

TopherGopher commented Apr 7, 2018 •

TopherGopher commented Apr 8, 2018 •

So I do have a workaround for folks who have a lot of files. TLDR; generate your own oauth creds and swap the default ones out, and then hack the max results in the list function to an insane number.

I changed these two lines of code and traded them out for creds I generated myself.
These creds are actually free to generate and use. Go to Google developer console, enable the Drive API, create «other» oauth creds, and then just paste them in and re-build grive.

I ended up using a simple Dockerfile to play around with building this (since my binary is currently installed from the apt repo, and I didn’t want to grab some of the dev libs), and thought I’d pass it along. Ignore if it’s worthless to you.

Save this as Dockerfile in the top directory of this repo

Because you’re not sharing your requests with other people anymore, you aren’t hitting the limits on the primary account. This also has the added benefit of you owning your own integration to your data.

piekniewski commented May 8, 2018

piekniewski commented May 8, 2018

OK, figured that out. grive will not update auth token for new credentials for previously downloaded drive. One has to create a fresh directory, get a new auth token and download everything from scratch.

TopherGopher commented May 8, 2018

alanmilinovic commented Jul 6, 2018

This is a show stopper for me. Getting this error all the time. Fix would be appreciated.

cserpell commented Aug 1, 2018

This happens to me all the time. It is really annoying. I’ve got aroung 60 GB in Drive, and it takes a long time to sync, but it works around a third of the times I run it. Otherwise, it gives the following error (and maybe others sometimes).

cserpell commented Aug 1, 2018 •

It seems @vitalif commited a fix 93cae25 that would help. Let’s see what happens.

edo0 commented Mar 17, 2019

Any update on this issue? Keeps on presenting itself to me.
$ grive
Reading local directories
Reading remote server file list
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 2 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 2 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 2 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 2 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»
>
>
). retrying in 1 seconds
request failed due to rate limiting: 403 (body: <
«error»: <
«errors»: [
<
«domain»: «usageLimits»,
«reason»: «rateLimitExceeded»,
«message»: «Rate Limit Exceeded»
>
],
«code»: 403,
«message»: «Rate Limit Exceeded»

jahagirdar commented Dec 23, 2020

I am using my own key pair, When I run

The URL on last list shows «Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.»

Am I missing something?

renedis commented Jan 30, 2021

same issue here.. Uploading 14.5TB and getting the error after 3.6TB on a 250/250 line.

You can’t perform that action at this time.

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.

Источник

API rate limit exceeded #16

Comments

Harmon758 commented Aug 23, 2019

I’m getting this error fairly consistently when using the action:

The text was updated successfully, but these errors were encountered:

damccorm commented Aug 26, 2019

Harmon758 commented Aug 26, 2019

damccorm commented Aug 26, 2019

I’ll try to dig in a little more and figure out what exactly is happening here

kjk commented Aug 26, 2019 •

Just an idea: data returned by https://api.github.com/repos/golang/go/git/refs/tags doesn’t change often so it could be stored directly in this repo and updated once a day via cron job (via GitHub Action Workflow, of course).

I did something like that so you can use that as inspiration:

It’s quite simple: a daily cron job updates some files in the repo and if they change, it checks them in.

A bonus of such change is that it would speed up the action (by removing an http request).

damccorm commented Aug 26, 2019

It also could create a weird situation where 12.x resolves to one Go version for v1.0.0 of this action, but to a different Go version for v1.1.0 of the action which seems non-ideal.

pelletier commented Aug 27, 2019

FYI, I am seeing this as well, trying to setup Github Actions on a public repo: https://github.com/pelletier/go-toml/pull/294/checks?check_run_id=204074095

Started happening after

1h of working on it.

kjk commented Aug 27, 2019

Probably relevant: the ip address hitting this limit is 199.7.166.17 which belongs to MacStadium.

I assume GitHub uses MacStadium for running OSX jobs and it seems they’re all behind the same proxy which is why they are hitting GitHub limit.

So if GitHub has such capability, you should whitelist that IP address.

nathany commented Aug 30, 2019

Also seeing this error here after adding macOS to the build matrix.

It also appears to have cancelled my Windows and Linux builds?

rate limit exceeded что делать. Смотреть фото rate limit exceeded что делать. Смотреть картинку rate limit exceeded что делать. Картинка про rate limit exceeded что делать. Фото rate limit exceeded что делать

Bios-Marcel commented Aug 30, 2019

Same IP, same symptoms. Depending on what the rate limit is, might it be possible to just delay the download instead of failing?

kjk commented Aug 30, 2019

Another option would be to attribute the call not to anonymous user but to a given GitHub user.

Actions already provide GITHUB_TOKEN secret of the repo’s owner. It’s just a matter of plugging it into that API call.

It might not be possible to just access it from the action but it would be possible to define github-token argument to the action, use it if provided and document that to avoid this rate limit, the user can provide it as:

Источник

Как жить с ограничениями внешних API на количество запросов

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

Мы уже рассказывали о том, как можно реализовать эти ограничения, если вы сами разрабатываете API сервиса, сегодня хотим рассказать о том, как жить с «клиентской» стороны и удобно пользоваться ограниченным по количеству запросов API.

rate limit exceeded что делать. Смотреть фото rate limit exceeded что делать. Смотреть картинку rate limit exceeded что делать. Картинка про rate limit exceeded что делать. Фото rate limit exceeded что делать

Вводные данные

Меня зовут Юрий Гаврилов, я работаю в команде Data Platfrom в ManyChat. У нас в компании есть маркетинговый отдел, который, среди всего прочего, любит общаться с нашими клиентами через сервис Intercom, позволяющий отправлять удобные In-App сообщения пользователю прямо в нашем веб-приложении. Чтобы эти коммуникации были осмысленными, Intercom должен получать некоторую информацию о наших клиентах (имя, дату регистрации, различные простые метрики их аккаунтов и т.д.). За предоставление этих данных в Intercom отвечает наш довольно-таки монолитный бекенд-компонент, хранящий информацию о наших пользователях. А ещё, совсем недавно, мы построили классный аналитический контур (о котором обязательно расскажем в следующих статьях), также хранящий кучу информации о наших пользователях, и довольно изолированный от упомянутого выше бекенд-компонента. В этом контуре аналитики обсчитывают более сложные пользовательские метрики, гоняют ML-алгоритмы и хранят витрины с результатами всех этих вычислений. Для ещё более крутых коммуникаций с клиентами, часть из этих результатов также хотелось бы иметь в Intercom.

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

rate limit exceeded что делать. Смотреть фото rate limit exceeded что делать. Смотреть картинку rate limit exceeded что делать. Картинка про rate limit exceeded что делать. Фото rate limit exceeded что делать

Мысли о решении проблемы вслух

Понятно, что хаотичный вызов методов внешнего ограниченного API из разных компонентов когда хочется, может быстро привести к неприятным последствиям. Прогрузка «продвинутых» данных из аналитического контура рано или поздно перебьет и не даст загрузиться важным «базовым» данным из бекенд-компонента, каким бы настойчивым и терпеливым мы его не настроили.

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

Реализация «единой точки общения»

Мы уже говорили, что в ManyChat любят Redis — он же нам помог для решения и этой задачи. Для создания такой «единой точки» нужно где-то собирать информацию о том, какие именно методы хотят вызвать во внешнем API наши компоненты. Если внешние компоненты захотят вызвать методов больше, чем позволено ограничениями API, на момент «передышки», пока не обновятся лимиты, эту информацию нужно где-то хранить. А ещё, нам бы очень хотелось ввести систему приоритетов, чтобы «базовые» данные, которые бекенд-компонент хочет отправить в Intercom, не ждали, пока прогрузится много «продвинутых» данных из аналитического контура.

Все эти проблемы позволяет решить Redis, а точнее структура данных List и реализованные на ней очереди.

На каждый приоритет нам нужно создать по своей очереди, в которую компоненты будут записывать свои намерения вызвать тот или иной метод в API, а один общий consumer будет в порядке приоритетности эти очереди вычитывать и непосредственно вызывать методы API. Если при вызове очереди он сталкивается с достижением rate-limit, он подождет, пока лимиты сбросятся, и продолжит работу.

В нашем случае очереди нужно две — для «базовых» данных из бекенд-компонента (давайте назовем её BackendQueue), и менее приоритетных «продвинутых» данных из аналитического контура (AnalyticsQueue). Прелесть такого подхода заключается также и в том, что совершенно не важно, на каких языках программирования написаны компоненты и consumer, все они смогут выполнять свою работу, нужно только определиться с форматом хранящихся в очереди данных.

Давайте для определенности и простоты примем в этой статье такой формат (JSON):

Тогда MVP нашего consumer’a может выглядеть так (PHP)

Здесь мы разбираем очереди в порядке приоритетов, при получении информации о методе пытаемся его выполнить, если сталкиваемся с лимитами — ждем и пытаемся снова ограниченное количество раз.

А наши компоненты на разных языках программирования могут отправлять запрос на вызов интересующего их метода:

Аналитический контур (Python):

rate limit exceeded что делать. Смотреть фото rate limit exceeded что делать. Смотреть картинку rate limit exceeded что делать. Картинка про rate limit exceeded что делать. Фото rate limit exceeded что делать

Проблемы метода и их решения

Однопоточность → немасштабируемость

Когда мы попытались перейти на такую систему — всё заработало, данные доходили до Intercom, лимиты не исчерпывались. Но возникла другая проблема — каждое обращение к внешнему сервису занимает какое-то время, и когда все вызовы API «сместились» в один поток, мы совсем перестали доходить до rate-limit, перформанс customer’a был в несколько раз меньше rate-limit’ов, и стало понятно, что нужно всю эту радость как-то распараллеливать. Redis вполне безопасно (в смысле параллельности) позволяет разбирать свои очереди нескольким consumer’ам. В целом, нет никакой проблемы в том, чтобы запустить несколько consumer’ов, описанных выше, на одни и те же очереди и проблемы не будет. Каждый из них будет точно так же с соблюдением приоритетности разбирать очередь и, при превышении лимитов, ждать, пока внешний сервис сбросит лимит, и далее работать снова до исчерпания лимита.

Но мы решили немного ограничить вызовы с нашей стороны, потерять несколько десятков возможных вызовов в пределах лимитов, и не доводить consumer’ов до ситуации, когда внешний сервис сообщает им о достижении лимита вызовов. Для этого мы рассчитали для каждого consumer’а его собственный лимит на количество вызовов в единицу времени, при достижении которого он перестает разбирать очередь и делать вызовы к API до перехода к следующему временному интервалу.

Пример самоконтролирующего лимиты consumer’a (PHP)

Одностороннее взаимодействие с API

Иногда бывает нужно не только вызвать какой-то метод во внешнем API, но и получить и обработать его ответ. Мы же перевели наше взаимодействие компонентов с API в асинхронный формат. Проблема получения ответа от сервера и доведения его до исходного компонента — решаемая. Достаточно дополнить данные о методе, который мы хотим выполнить, данными о callback’e, который consumer’у необходимо выполнить при получении ответа от внешнего сервиса. Мы написали несколько стандартных callback’ов, которые складывают полученные ответы в определенные очереди, из которых компоненты могут их прочитать и обработать самостоятельно.

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

Что делать, когда запросов становится настолько много, что очереди разгребаются часами/днями/неделями?

Здесь мы точно не волшебники, и запрограммировать свое взаимодействие с внешним API так, чтобы превышать его rate-limit, мы точно не можем. По задачам загрузки данных наших клиентов мы внедрили у себя систему по учету тех данных, что уже были отправлены во внешний сервис. Когда наступает очередная выгрузка данных о пользователях, отправляются только данные о тех пользователях, которые обновились, и, тем самым, уменьшается необходимое количество запросов.

В остальном, в данной ситуации не остаётся ничего иного, кроме как разговаривать со внешним сервисом на тему увеличения лимита запросов.

Заключение

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

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *