Разрешить только один внутренний вызов в Azure API Manager - PullRequest
0 голосов
/ 27 июня 2018

У нас есть старый веб-сервис, который возвращает некоторые данные через 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.

  1. 5 пользователей звонят в сервис.
  2. Первый вызов переходит к внутреннему API, остальные 4 помещаются в очередь ожидания.
  3. Когда возвращается результат первого вызова, он затем кэшируется.
  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>

1 Ответ

0 голосов
/ 27 июня 2018

В настоящее время лимит-параллелизм работает только на уровне узла. Таким образом, это позволит только один вызов бэкэнду, только если у вас есть экземпляр Dev APIM. В случае Basic, Std или Prem у вас есть минимум два узла (1 единица = 2 узла), поэтому такая конфигурация позволит не более двух параллельных вызовов под нагрузкой.

Теперь, если вы укажете max-count = X внутри на уровне узла, мы установим ограничение на X / node_count. Конечно, мы не можем установить его на 0, поэтому 1 - это минимум. Таким образом, это всегда как минимум количество вызовов node_count.

Мы будем обновлять эту политику в будущем для поддержки синхронизации между узлами.

...