在Java中限制RESTAPI

在Java中限制RESTAPI,java,rest,dropwizard,throttling,Java,Rest,Dropwizard,Throttling,我想添加一种方法来限制来自某个客户端的每个API上的请求数量。所以,我想基本上限制每个客户端每个API的请求数量 我使用DropWizard作为框架。有人能推荐实现这一目标的方法吗?我需要一种适用于分布式系统的方法。一种简单的方法是使用一个函数,并将它包装在web.xml中的所有API调用中。假设您的客户端发送一个在HTTP头中标识它们的API密钥,您可以实现如下过滤器: public class MyThrottlingFilter extends Filter { public v

我想添加一种方法来限制来自某个客户端的每个API上的请求数量。所以,我想基本上限制每个客户端每个API的请求数量


我使用DropWizard作为框架。有人能推荐实现这一目标的方法吗?我需要一种适用于分布式系统的方法。

一种简单的方法是使用一个函数,并将它包装在
web.xml
中的所有API调用中。假设您的客户端发送一个在HTTP头中标识它们的API密钥,您可以实现如下过滤器:

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>
然后像这样注册它:

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>

MyThrottlingFilter
com.my.throttler.MyThrottlingFilter
MyThrottlingFilter
/*

当然,如果您使用其他身份验证方法,识别您的客户可能会比这更困难,但总体思路应该是相同的。

我认为类似的拦截器可以解决这个问题。

您想在应用程序中包含这样的逻辑吗?也许一些外部负载平衡器会是更好的选择

您可以尝试HAProxy,并在应用程序之外使用整个Thlotling逻辑


这种方法的一大优点是,无论何时抛出需求发生变化,您都不必重新构建和重新部署应用程序。此外,与典型的Java应用程序相比,HAProxy重新启动所需的时间要少得多。

如果您必须在Dropwizard中使用它,那么我会按照npe的建议执行。 所需的更改是通过外部流程(如redis)共享“费率”

因此,在npe的示例中,
invocationLimitNotReach
将检查redis主机以确定当前速率(可能它存储了所有当前请求的列表),并且添加当前请求是否会超过该阈值


如果添加当前请求不会超过允许的速率,则将请求添加到列表中,当请求完成时,将请求从redis列表中删除。redis列表条目可以有一个TTL,因此如果一个为20个请求提供服务的dropwizard实例在TTL之后突然消失,它们将从“当前正在执行的请求”列表中删除。

基于npe给出的答案,您可以“实现分布式”-通过将每个用户的API命中计数存储在诸如Redis这样的中央存储中,InvocationLimitNotReach(apiKey)方法随后可以使用该存储来确定违反速率限制的情况


当然,最困难的部分是确定如何“终止”超出限制窗口的点击数。

如果您希望利率限制而不是硬限制,请不要忽略:谢谢condit。。。。。这正是我想要的…这很好。但我正在寻找一个分布式解决方案,即将工作在vip上,而不是直接在机器上。如果可能的话,请提出建议。这很好。但我正在寻找一个分布式解决方案,即将工作在vip上,而不是直接在机器上。如果可能的话,请提出建议。然后我会选择负载平衡器。尝试使用
mod\u proxy\u balancer
HAProxy
as设置apache。但这与您最初提出的问题无关,与
DropWizard
和Java完全无关。这很好。但我正在寻找一个分布式解决方案,即将工作在vip上,而不是直接在机器上。如果可能的话,请提出建议。