1. 概述
在本文中,我們將繼續改進我們的小型 Reddit 應用,通過限制其對實時 Reddit API 的訪問。
基本思路是確保我們不要頻繁地訪問他們的 API——否則 Reddit 會開始阻止請求。我們將充分利用 Guava 的 RateLimiter 來實現這一目標。
2. 一個自定義 RedditTemplate
首先,我們創建一個 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 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 param = new HashMap();
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();
}
}
這裏有一些有趣的事情正在發生。
首先——我們正在使用 Session作用域用於此 Bean——僅僅是為了確保應用程序中的每個用户/會話都能獲得自己的 RedditTemplate實例。
現在——OAuth2RestTemplate已經支持將憑據作用域化,但我們在此基礎上進行了擴展,使實際的 Bean 實例具有作用域,以便我們還可以為每個用户單獨進行速率限制。
這導致了實際的速率限制邏輯——簡單地説,我們正在使用 Guava RateLimiter來獲取許可在允許請求通過並命中實時 API 之前。
3. The RedditController
接下來,讓我們在 RedditTemplate 中使用這個新模板 – 例如:
@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. 結論
在本案例研究的這一部分,我們為 Reddit 應用程序添加了速率限制,以確保我們不會因過多的活動而被實時 API 阻止。
這並非理論問題——事實上,我曾多次在應用程序中使用時遇到它。
正是這種小改進最終將導致一個成熟且易於使用的應用程序——因此我對這一步驟感到興奮。