Rate Limiting Access to the Reddit API – 限制对Reddit API的访问率

最后修改: 2015年 5月 20日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick article we’re going to continue improving our small Reddit app by rate limiting the way it has access to the live Reddit API.

在这篇快速文章中,我们将继续改进我们的小型 Reddit 应用程序,方法是对其访问实时 Reddit API 的方式进行速率限制

The simple idea is that we want to make sure we don’t hit their API to much – otherwise Reddit will start blocking the requests. We’re going to make good use of the Guava RateLimiter to get there.

简单的想法是,我们要确保我们不会过多地攻击他们的API–否则Reddit将开始阻止请求。我们要好好利用Guava的RateLimiter来达到这个目的。

2. A Custom RedditTemplate

2.一个自定义的RedditTemplate

First, let’s create a Reddit template – a small client for the Reddit API – which will consolidate all low level communication to a single component:

首先,让我们创建一个Reddit模板–Reddit API的小客户端–它将把所有低级别的通信整合到一个组件中。

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RedditTemplate {

    @Autowired
    @Qualifier("redditRestTemplate")
    private OAuth2RestTemplate redditRestTemplate;

    private RateLimiter rateLimiter;

    public RedditTemplate() {
        rateLimiter = RateLimiter.create(1);
    }
    
    public JsonNode getUserInfo() {
        rateLimiter.acquire();
        return redditRestTemplate.getForObject(
          "https://oauth.reddit.com/api/v1/me", JsonNode.class);
    }
    
    public JsonNode submitPost(MultiValueMap<String, String> params) {
        rateLimiter.acquire();
        return redditRestTemplate.postForObject(
          "https://oauth.reddit.com/api/submit", params, JsonNode.class);
    }
    
    public String needsCaptcha() {
        rateLimiter.acquire();
        return redditRestTemplate.getForObject(
          "https://oauth.reddit.com/api/needs_captcha.json", String.class);
    }
    
    public String getNewCaptcha() {
        rateLimiter.acquire();
        Map<String, String> param = new HashMap<String, String>();
        param.put("api_type", "json");
        return redditRestTemplate.postForObject(
          "https://oauth.reddit.com/api/new_captcha", param, String.class, param);
    }
    
    public OAuth2AccessToken getAccessToken() {
        rateLimiter.acquire();
        return redditRestTemplate.getAccessToken();
    }
}

A few interesting things are happening here.

这里正在发生一些有趣的事情。

First – we’re using the Session scope for this bean – simply so that each user/session in our app will get its own RedditTemplate instance.

首先–我们为这个Bean使用Session作用域–只是为了让我们应用中的每个用户/会话得到自己的RedditTemplate实例。

Now – the OAuth2RestTemplate already has support for keeping credentials session scoped, but we’re going beyond that here and making the actual bean instance session scoped – so that we can also rate limit each user separately.

现在–OAuth2RestTemplate已经支持保持凭证的会话范围,但我们在这里超越了这一点,使实际的bean实例成为会话范围–这样我们也可以单独限制每个用户的速率

Which leads us to the actual rate limiting logic – simply put, we’re using the Guava RateLimiter to acquire a permit before letting the request through and hitting the live API.

这让我们看到了实际的速率限制逻辑–简单地说,我们正在使用Guava的RateLimiter来获得许可,然后让请求通过并击中实时API。

3. The RedditController

3、RedditController

Next – let’s start using this new RedditTemplate in the RedditContoller – for example:

接下来–让我们开始在RedditTemplate中使用这个新的RedditContoller–比如说。

@Controller
public class RedditController {
    @Autowired
    private RedditTemplate redditTemplate;

    @Autowired
    private UserRepository userReopsitory;

    @RequestMapping("/login")
    public String redditLogin() {
        JsonNode node = redditTemplate.getUserInfo();
        
        loadAuthentication(node.get("name").asText(), 
          redditTemplate.getAccessToken());
        return "redirect:home.html";
    }
}

4. Conclusion

4.结论

In this part of the Case Study we added rate limiting to the Reddit application, to make sure we’re not blocked by the live API for to much activity.

在案例研究的这一部分,我们为Reddit应用程序添加了速率限制,以确保我们不会因为活动太多而被实时API阻止

This isn’t a theoretical problem either – but actually something that I ran into a couple of times using the app.

这也不是一个理论上的问题–但实际上我在使用该应用程序时遇到过几次。

It’s this kinds of small improvements that are eventually going to lead to a mature and usable application – so I’m excited about this particular step.

正是这种小的改进,最终将导致一个成熟和可用的应用程序–所以我对这个特殊的步骤感到兴奋。