Ограничить количество параллельных запросов пользователем
Я хочу ограничить свои продукты следующим образом:
- стартер: параллельных вызовов нет (разрешены только синхронные вызовы)
- премиум: 10 параллельных вызовов (разрешить асинхронный вызов с ограничением)
Службе за шлюзом API требуется некоторое время, поэтому некоторые люди хотят делать асинхронные вызовы, чтобы получить больше результатов.
Единственные ограничения, которые я нашел из лазури, - это ограничения скорости и квоты. Но их ограничения для звонков за раз, мне это нужно для параллельных звонков.
Я думал об этой логике:
<inbound>
<http-call>
send user id to a azure function, that increases the counter for the user, returns the current counter
</http-call>
<when>
compare counter value with the product limit (x = 0 for starter or x <= 10 for premium)
if true route to the service, if false generate a "too many requests" response
</when>
</inbound>
<outbound>
<http-call>
decrease the counter
</http-call>
</outbound>
Я не уверен, что это лучшая логика, потому что функция требует времени для обновления значений. Есть ли способ хранить какую-то "разделяемую переменную", к которой могут обращаться все запросы для проверки счетчика в управлении API, а не с помощью внешней функции?
1 ответ
Я нашел способ кеширования (я думаю, что функция кеширования является глобальной, но это не доказано. У вас просто есть кешированный массив, который будет идентифицировать пользователя в качестве ключей и определять количество параллельных запросов):
<inbound>
<set-variable name="user-id" value="@(context.User.Id)" />
<!--Look for user-counter for this user in the cache -->
<cache-lookup-value key="@("user-counter-" + context.Variables["user-id"])" variable-name="user-counter" />
<choose>
<!-- check the limit -->
<when condition="@(context.Variables.ContainsKey("user-counter"))">
<choose>
<!-- -->
<when condition="@((int)context.Variables["user-counter"] > 0)">
<return-response>
<set-status code="429" reason="TOO MANY REQUESTS" />
<set-body>too many parallel requests</set-body>
</return-response>
</when>
<when condition="@((int)context.Variables["user-counter"] <= 0)">
<cache-store-value key="@("user-counter-" + context.Variables["user-id"])" value="@((int)context.Variables["user-counter"] + 1)" duration="100000" />
</when>
</choose>
</when>
<!-- If we don’t find it in the cache, create it with the value 1 -->
<when condition="@(!context.Variables.ContainsKey("user-counter"))">
<cache-store-value key="@("user-counter-" + context.Variables["user-id"])" value="0" duration="100000" />
</when>
</choose>
</inbound>
<outbound>
<base />
<!-- remove user-counter -->
<cache-lookup-value key="@("user-counter-" + context.Variables["user-id"])" variable-name="user-counter-old" />
<cache-store-value key="@("user-counter-" + context.Variables["user-id"])" value="@((int)context.Variables["user-counter-old"] - 1)" duration="100000" />
</outbound>