知識庫 / Spring RSS 訂閱

限制 Reddit API 訪問速率

REST,Spring
HongKong
4
04:00 AM · Dec 06 ,2025

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<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();
    }
}

這裏發生了一些有趣的事情。

首先,我們正在使用 Session 作用域來處理這個 Bean——這僅僅是為了確保每個用户/會話在我們的應用程序中都能獲得自己的 RedditTemplate 實例。

現在,OAuth2RestTemplate 已經支持保持憑據在會話作用域中,但我們在此基礎上進行了擴展,將實際的 Bean 實例也設置為會話作用域——這樣我們就可以單獨對每個用户進行限速。

這引出了實際的限速邏輯——簡單來説,我們使用 Guava 的 RateLimiter 來在將請求通過並訪問實時 API 之前獲取一個許可。

3. 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 阻止

這並非理論問題——事實上,我曾多次在實際使用應用時遇到類似情況。

正是這種微小的改進最終將導致一個成熟且易於使用的應用程序——因此我對這一步驟感到興奮。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.