ThinkPHP接口防高频调用有五种方式:一、用think-throttle中间件路由级限流;二、RateLimit中间件分组统一限流;三、自定义中间件实现接口维度独立限流;四、Nginx反向代理层IP级速率控制;五、基于Redis原子操作手写限流逻辑。

如果您在ThinkPHP项目中需要防止接口被恶意高频调用,导致服务器资源耗尽或数据异常,则需对特定接口实施访问频率限制。以下是多种可行的实现方式:
一、使用topthink/think-throttle中间件进行路由级限流
该方案基于官方生态扩展,通过Throttle中间件对单个路由或路由分组施加固定窗口计数限流,依赖缓存驱动存储请求计数,配置简洁且开箱即用。
1、执行命令安装扩展:composer require topthink/think-throttle
2、确认config/throttle.php配置文件已生成;若缺失,运行php think vendor:publish发布配置
立即学习“PHP免费学习笔记(深入)”;
3、在app/middleware.php中注册中间件类:\think\middleware\Throttle::class
4、在路由定义中显式绑定并指定参数,例如:Route::get('api/data', 'Api/Data.index')->middleware(\think\middleware\Throttle::class, ['visit_rate' => '5/m', 'key' => '__IP__']);
5、修改config/throttle.php中的visit_method数组,确保包含目标HTTP方法,如['GET', 'POST']
二、通过RateLimit中间件配置分组统一限流
该方式适用于API模块整体限流场景,利用TP6内置RateLimit中间件配合路由分组,避免逐条路由重复声明,提升可维护性。
1、确认app/http/middleware/RateLimit.php类存在,且已在config/middleware.php中注册路径
2、在app/route/app.php中定义API分组并挂载中间件:Route::group('api', function () { Route::get('user', 'User/index'); })->middleware('throttle:60,1');
3、检查config/rate_limit.php中max_attempts与decay_minutes值,例如设置'decay_minutes' => 0.5表示30秒窗口
4、确保cache驱动已切换至Redis:在config/cache.php中将default设为'redis',并验证config/redis.php连接可用
5、若需按登录用户限流,新建继承类app\http\middleware\UserRateLimit,重写getLimitedId()方法返回$request->user()->id ?? $request->ip()
三、自定义中间件实现接口维度独立限流
当多个路由共用同一控制器方法(如RESTful的index),默认Throttle会共享计数器,此时需手动构造唯一键名以保障各接口独立计数。
1、复制vendor/topthink/think-throttle/src/middleware/ThrottleRequests.php至app/middleware/CustomThrottle.php
2、重写getLimitedKey()方法,拼接$request->rule()或$request->url(true),例如:return 'throttle_api_' . md5($request->url(true) . $request->ip());
3、在config/middleware.php中注册新中间件:\app\middleware\CustomThrottle::class
4、在对应路由中调用:->middleware(\app\middleware\CustomThrottle::class, ['visit_rate' => '10/m'])
5、若$route为空(闭包路由),fallback使用$request->path()替代,确保键名稳定
四、在Nginx反向代理层实施IP级请求速率控制
该方式不依赖PHP应用逻辑,直接在入口网关拦截超频请求,降低后端压力,适合应对CC攻击或突发流量。
1、编辑Nginx主配置文件,在http块内添加限流区域:limit_req_zone $binary_remote_addr zone=nginxapi:10m rate=15r/s;
2、在server或location块中引用该区域,例如针对/api路径:location ^~ /api/ { limit_req zone=nginxapi burst=30 nodelay; }
3、确保Nginx已启用ngx_http_limit_req_module模块,可通过nginx -V 2>&1 | grep -o with-http_limit_req_module验证
4、配置proxy_set_header指令透传真实IP:proxy_set_header X-Real-IP $remote_addr;
5、重启Nginx服务使配置生效:systemctl reload nginx
五、基于Redis原子操作手写限流逻辑
该方式绕过框架中间件,完全自主控制限流粒度与算法,支持滑动窗口等高级策略,适用于高并发核心接口。
1、在接口入口处获取客户端IP:$ip = $request->header('x-real-ip', $request->ip());
2、构造唯一键名并执行原子递增:$key = 'api_limit:' . md5($ip . '/user/export');
3、调用Redis的INCR与EXPIRE命令:$redis->incr($key); $redis->expire($key, 60);
4、读取当前计数值:$count = $redis->get($key) ?: 0;
5、判断是否超限并中断响应:if ($count > 100) { return response('Too many requests', 429); }



















