Ограничить количество параллельных запросов пользователем

Я хочу ограничить свои продукты следующим образом:

  • стартер: параллельных вызовов нет (разрешены только синхронные вызовы)
  • премиум: 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>
Другие вопросы по тегам