php实现接口限流

php接口限流主要是防止高并发造成服务器扛不住的情况下,需要限制数据的获取,简单实现就是结合redis实现。

<?php

/**
 * api 接口限流
 *
 */

class api
{

    public function get_client_ip($type = 0) {
        $type       =  $type ? 1 : 0;
        static $ip  =   NULL;
        if ($ip !== NULL) return $ip[$type];
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $pos    =   array_search('unknown',$arr);
            if(false !== $pos) unset($arr[$pos]);
            $ip     =   trim($arr[0]);
        }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $ip     =   $_SERVER['HTTP_CLIENT_IP'];
        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip     =   $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = ip2long($ip);
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }

    public function test()
    {

        //接口时间限流,这种方式可以防止钻时间漏洞无限的访问接口 比如在59秒的时候访问,就钻了空子
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $ip = $this->get_client_ip(true);
        $len = $redis->lLen($ip);
        if($len === 0)
        {
            $redis->lPush($ip,time());
            echo "访问1次<br>";
            $redis->expire($ip,60);
        }else{
            //判断有没有超过1分钟
            $max_time = $redis->lRange($ip,0,0);
            //判断最后一次访问的时间比对是否超过了1分钟
            if((time()- $max_time[0]) < 60){
                if($len> 10){

                    echo '访问超过了限制';
                }else{

                    $redis->lPush($ip,time());
                    echo "访问{$len}次<br>";
                }
            }
        }
    }

}
(new api())->test();

 

### FastAdmin框架中的接口限流实现方法 FastAdmin 是基于 ThinkPHP5 和 Bootstrap 构建的一个极速后台开发框架[^3]。该框架提供了丰富的功能模块,可以满足大多数后端管理系统的开发需求。对于接口限流的功能,在 FastAdmin 中可以通过配置文件或者自定义逻辑来实现。 #### 1. 使用环境变量控制开关 在 FastAdmin 的 `.env` 文件中设置一个 `RATE_LIMITING-STATUS` 开关,用于全局启用或禁用当前的限流机制[^1]。通过这种方式,开发者可以在不修改代码的情况下灵活调整限流状态。 ```ini # .env 配置示例 RATE_LIMITING_STATUS=true ``` 当此参数被设为 `true` 时,表示启用了接口限流功能;反之则关闭限流。 --- #### 2. 基于 Redis 实现令牌桶算法 为了更精确地控制接口访问频率,通常会采用 **Redis** 结合 **令牌桶算法** 来实现限流。以下是具体实现方式: ##### (1) 安装依赖 确保项目已经安装了 Redis 扩展及其 PHP 驱动程序。如果尚未安装,可通过 Composer 添加相关依赖项: ```bash composer require predis/predis ``` ##### (2) 创建中间件 在 FastAdmin 中创建一个新的中间件(Middleware),专门处理请求速率限制逻辑。例如,命名为 `RateLimiting.php`。 ```php <?php namespace app\common\middleware; use think\Request; use Predis\Client; class RateLimiting { protected $redis; protected $limit; // 单位时间内允许的最大请求数 protected $duration; // 时间窗口长度(秒) public function __construct() { $this->redis = new Client(); $this->limit = config('rate_limit.limit') ?? 60; // 默认每分钟最多60次 $this->duration = config('rate_limit.duration') ?? 60; // 默认时间窗口为60秒 } public function handle(Request $request, \Closure $next) { $key = 'ratelimit:' . $request->ip(); // 根据IP生成唯一键名 $currentRequests = $this->redis->get($key); if ($currentRequests === null || intval($currentRequests) >= $this->limit) { header('X-Rate-Limit-Limit', $this->limit); header('X-Rate-Limit-Remaining', 0); return json(['code' => 429, 'msg' => 'Too Many Requests'], 429); // 返回HTTP状态码429 Too Many Requests } else { $this->redis->incrby($key, 1); // 请求计数加一 $this->redis->expire($key, $this->duration); // 设置过期时间 header('X-Rate-Limit-Limit', $this->limit); header('X-Rate-Limit-Remaining', $this->limit - intval($currentRequests)); } return $next($request); } } ``` 在此代码片段中,我们利用 Redis 存储每个 IP 地址对应的请求次数,并设置了固定的时间窗口大小。一旦某个用户的请求超出设定阈值,则返回错误响应并提示“Too Many Requests”。 --- #### 3. 配置应用层支持 最后一步是在项目的入口处注册上述中间件。编辑 `application/middleware.php` 文件,添加如下内容: ```php return [ // ...其他中间件... \app\common\middleware\RateLimiting::class, ]; ``` 这样就可以让整个应用程序自动加载接口限流中间件。 --- ### 总结 综上所述,FastAdmin 框架下的接口限流主要依靠外部工具(如 Redis)配合内部业务逻辑完成。通过合理配置 `.env` 参数以及编写高效的中间件脚本,能够有效保障 API 接口的安全性和稳定性[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值