У нас есть старый веб-сервис, который возвращает некоторые данные через API. Этот сервис очень медленный, и не нужно выполнять много вопросов через API одновременно. Теперь новое веб-приложение Azure было разработано другой частью компании. Они называют этот медленный API и не понимали, насколько это было плохо, пока мы не встретились о том, почему сервер баз данных почти вышел из строя. Для ответа API иногда требуется 4–8 секунд, что не является оптимальным, если многие потребители вызывают его 50 раз.
Я добавил Azure API Manager между старым API и новым веб-приложением Azure. Я надеялся, что смогу ограничить количество обращений к бэкэнду, а затем использовать кеш для уменьшения количества вызовов. Тем не менее, эта новая служба требует «быстрых данных» и хочет вызывать бэкэнд по крайней мере каждые 10 секунд. Я не хочу, чтобы Azure API Manager вызывал бэкэнд больше, чем нужно, что переводится в: те же вопросы = кеширование в течение 10 секунд, затем извлечение из бэкенда, новый параметр = извлечение из бэкэнда и затем кеширование в течение 10 секунд.
Кэш работает, но каждые 10 секунд я получаю множество «одновременных» вызовов через Azure API Manager, что усложняет жизнь старому API.
Можно ли разрешить только один вызов (для авторизации и параметра) в API, а затем кэшировать результат? Это означает, что, если 5 пользователей одновременно задают API Manager один и тот же вопрос, первый из них отправляется на сервер, возвращает ответ, который кэшируется, а остальные 4 помещаются в очередь в ожидании завершения кэшированной копии? Я бы предпочел провести цикл повторных попыток на несколько секунд, а не возвращать ошибку слишком большого числа вызовов.
Ex.
- 5 пользователей звонят в сервис.
- Первый вызов переходит к внутреннему API, остальные 4 помещаются в очередь ожидания.
- Когда возвращается результат первого вызова, он затем кэшируется.
- Остальные 4 вызова теперь могут извлечь кэшированную копию и вернуть ее.
Я пробовал несколько различных вариантов правил, таких как попытка ограничения параллелизма внутри повторения, но все это приводит к множественным вызовам бэкэнда до тех пор, пока первый не вернется и не будет кэширован.
<policies>
<inbound>
<base />
<cache-lookup vary-by-developer="false" vary-by-developer-groups="false" allow-private-response-caching="true" downstream-caching-type="none">
<vary-by-header>Accept</vary-by-header>
<vary-by-header>Accept-Charset</vary-by-header>
<vary-by-header>Authorization</vary-by-header>
</cache-lookup>
<retry condition="true" count="8" interval="1" first-fast-retry="false">
</retry>
</inbound>
<backend>
<limit-concurrency key="backend-server" max-count="1">
<forward-request timeout="60" />
</limit-concurrency>
</backend>
...
</policies>