Skip to content

Conversation

@ShellMonster
Copy link
Contributor

功能概述

为 feapder 框架添加域名级 QPS(每秒请求数)限制功能,支持为不同域名设置独立的请求速率限制;
主要用于使用feapder时,针对部分额外的服务的域名(非主要爬取)进行限制,避免QPS超出。

核心特性

  • ✅ 支持所有 Spider 类型(AirSpider、Spider、TaskSpider、BatchSpider)
  • ✅ 灵活的域名匹配策略(精确匹配、通配符匹配、www回退)
  • ✅ 分布式友好(基于 Redis 的多机器 QPS 配额共享)
  • ✅ 非阻塞设计(延迟调度机制,不阻塞工作线程)
  • ✅ 开箱即用(只需配置,无需编写代码)
  • ✅ 容错能力强(Redis 异常时自动降级)

技术实现

令牌桶算法

  • AirSpider: 本地内存版令牌桶(线程安全)
  • 分布式 Spider: Redis 分布式令牌桶(Lua 脚本保证原子性)

核心组件

  1. LocalTokenBucket: 本地内存令牌桶
  2. RedisTokenBucket: Redis 分布式令牌桶
  3. DomainRateLimiter: 统一管理器,自动选择令牌桶类型

使用示例

class MySpider(feapder.Spider):
    __custom_setting__ = dict(
        DOMAIN_RATE_LIMIT_ENABLE=True,
        DOMAIN_RATE_LIMIT_DEFAULT=10,
        DOMAIN_RATE_LIMIT_RULES={
            "baidu.com": 5,
            "*.google.com": 8,
        }
    )

修改文件

新增文件

  • feapder/utils/rate_limiter.py: 令牌桶算法实现(~300行)
  • docs/usage/域名级QPS限制.md: 完整使用文档
  • test_qps_limit.py: 功能测试脚本

修改文件

  • feapder/setting.py: 新增 QPS 相关配置项
  • feapder/network/request.py: 在 get_response() 中添加 QPS 检查逻辑
  • feapder/core/scheduler.py: 传递 redis_key 给 Request 类
  • feapder/core/parser_control.py: 注入 request_buffer 到请求对象
  • feapder/templates/*.tmpl: 在 4 个模板中添加 QPS 配置示例
  • docs/_sidebar.md: 添加文档导航

## 功能概述

为 feapder 框架添加域名级 QPS(每秒请求数)限制功能,支持为不同域名设置独立的请求速率限制。

## 核心特性

- ✅ 支持所有 Spider 类型(AirSpider、Spider、TaskSpider、BatchSpider)
- ✅ 灵活的域名匹配策略(精确匹配、通配符匹配、www回退)
- ✅ 分布式友好(基于 Redis 的多机器 QPS 配额共享)
- ✅ 非阻塞设计(延迟调度机制,不阻塞工作线程)
- ✅ 开箱即用(只需配置,无需编写代码)
- ✅ 容错能力强(Redis 异常时自动降级)

## 技术实现

### 令牌桶算法
- **AirSpider**: 本地内存版令牌桶(线程安全)
- **分布式 Spider**: Redis 分布式令牌桶(Lua 脚本保证原子性)

### 核心组件
1. `LocalTokenBucket`: 本地内存令牌桶
2. `RedisTokenBucket`: Redis 分布式令牌桶
3. `DomainRateLimiter`: 统一管理器,自动选择令牌桶类型

## 使用示例

```python
class MySpider(feapder.Spider):
    __custom_setting__ = dict(
        DOMAIN_RATE_LIMIT_ENABLE=True,
        DOMAIN_RATE_LIMIT_DEFAULT=10,
        DOMAIN_RATE_LIMIT_RULES={
            "baidu.com": 5,
            "*.google.com": 8,
        }
    )
```

## 修改文件

### 新增文件
- `feapder/utils/rate_limiter.py`: 令牌桶算法实现(~300行)
- `docs/usage/域名级QPS限制.md`: 完整使用文档
- `test_qps_limit.py`: 功能测试脚本

### 修改文件
- `feapder/setting.py`: 新增 QPS 相关配置项
- `feapder/network/request.py`: 在 get_response() 中添加 QPS 检查逻辑
- `feapder/core/scheduler.py`: 传递 redis_key 给 Request 类
- `feapder/core/parser_control.py`: 注入 request_buffer 到请求对象
- `feapder/templates/*.tmpl`: 在 4 个模板中添加 QPS 配置示例
- `docs/_sidebar.md`: 添加文档导航

## 测试

✅ 域名提取功能测试通过
✅ 本地令牌桶算法测试通过
✅ 代码语法检查通过

## 相关文档

- 技术方案: `域名级QPS限制技术方案.md`
- 使用文档: `docs/usage/域名级QPS限制.md`
@Boris-code
Copy link
Owner

看起来很强,周末测试后发版

将默认 QPS 限制从 10 改为 0,表示未配置的域名默认不限制。
只有在 DOMAIN_RATE_LIMIT_RULES 中明确配置的域名才会被限制。

修改文件:
- feapder/setting.py
- feapder/templates/air_spider_template.tmpl
- feapder/templates/spider_template.tmpl
- feapder/templates/batch_spider_template.tmpl
- feapder/templates/task_spider_template.tmpl
@ShellMonster
Copy link
Contributor Author

默认值改为0了,没加在域名限制里的,都正常发请求不被qps限制

@ShellMonster
Copy link
Contributor Author

多线程并发时会有抢,以及放进去又拿出来的情况,需要重新规划下方案,用单线程来管理分发。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants