2015-04-28 11 views
3

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

Я использую DropWizard в качестве рамки. Может ли кто-нибудь рекомендовать способы достижения этого? Мне нужно что-то, что будет работать для распределенной системы.

+1

Если yo'er ищет ограничение по лимиту вместо жесткого ограничения, не пропустите: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/util/concurrent/RateLimiter. html – condit

+0

Спасибо condit ..... это именно то, что я искал ... – hatellla

+0

Это хорошо. Но я ищу распределенное решение, то есть которое будет работать на vip вместо машины напрямую. Пожалуйста, предложите, если это возможно. – hatellla

ответ

5

Простейшим подходом было бы использовать Filter и обернуть его вокруг всех вызовов API в web.xml. Предполагая, что ваши клиенты подмигнуть, ключи API, идентифицирующие их в заголовке HTTP, можно реализовать фильтр так:

public class MyThrottlingFilter extends Filter { 

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 

     HttpServletRequest httpreq = (HttpServletRequest) req; 
     String apiKey = httpreq.getHeader("API_KEY") 

     if (invocationLimitNotReached(apiKey)) 
      chain.doFilter(req, res); 
     else 
      throw ... 
    } 
} 

, а затем зарегистрировать его как это:

<filter> 
    <filter-name>MyThrottlingFilter</filter-name> 
    <filter-class>com.my.throttler.MyThrottlingFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>MyThrottlingFilter</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping> 

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

+0

Это хорошо. Но я ищу распределенное решение, т. Е.который будет работать на vip вместо машины напрямую. Пожалуйста, предложите, если это возможно. – hatellla

+0

Тогда я бы пошел с балансиром нагрузки. Попробуйте установить apache с помощью 'mod_proxy_balancer' или' HAProxy', как показано в [R4J] (http://stackoverflow.com/a/29928406/1344008). Но это не имеет никакого отношения к вопросу, который вы изначально задали, и полностью не связан с «DropWizard» и Java. – npe

1

Я думаю, что такой перехватчик, как HandlerInterceptor, решит цель.

+0

Это хорошо. Но я ищу распределенное решение, то есть которое будет работать на vip вместо машины напрямую. Пожалуйста, предложите, если это возможно. – hatellla

4

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

Вы можете попробовать HAProxy и иметь всю логику throtlling вне вашего приложения.

Большим преимуществом такого подхода является то, что вам не пришлось бы перестраивать и передислоцировать приложение всякий раз, когда изменяются требования throtlling. Кроме того, для перезапуска HAProxy потребуется гораздо меньше времени, чем обычное Java-приложение.

0

Если вы абсолютно должны иметь его в Dropwizard, тогда я буду делать то, что предлагает npe. Необходимое изменение состоит в том, чтобы совместно использовать «скорость» через внешний процесс, например. Redis.

Так, например, в примере npe invocationLimitNotReached проверит хост redis, чтобы выяснить, какова текущая скорость (возможно, он хранит список всех текущих запросов), и если добавление текущего запроса будет проходить через этот порог.

Если добавление текущего запроса не будет превышать допустимую ставку, то вы добавите запрос в список, а когда запрос будет завершен, вы удалите запрос из списка redis. Элементы списка redis могут иметь TTL, поэтому, если экземпляр dropwizard, обслуживающий 20 запросов, внезапно исчезает, после TTL они удаляются из списка «выполняемых в настоящее время запросов».

0

Основываясь на ответе, заданном npe, вы можете «достигнуть распределенной» -постоянности, сохранив количество хитов для каждого пользователя API в центральном хранилище, таком как Redis, который затем может использовать метод invocationLimitNotReached (apiKey) для определения ограничений предельного уровня.

Жесткая часть, конечно же, заключается в определении того, как «истекать» количество попаданий, попадающих за пределы вашего предельного окна.