当前位置:首页 > PHP

php实现ip限流

2026-02-15 21:42:48PHP

PHP实现IP限流的方法

使用Redis实现令牌桶算法

Redis的原子操作和高效性适合实现令牌桶算法。以下是一个基于Redis的PHP实现示例:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);

$ip = $_SERVER['REMOTE_ADDR'];
$key = "rate_limit:$ip";
$capacity = 10; // 桶容量
$rate = 1; // 每秒添加的令牌数
$now = microtime(true);

$redis->watch($key);
$data = $redis->hGetAll($key);
$tokens = isset($data['tokens']) ? $data['tokens'] : $capacity;
$lastTime = isset($data['last_time']) ? $data['last_time'] : $now;

$delta = max(0, $now - $lastTime);
$newTokens = min($capacity, $tokens + $delta * $rate);

if ($newTokens < 1) {
    $redis->unwatch();
    header('HTTP/1.1 429 Too Many Requests');
    exit;
}

$redis->multi();
$redis->hSet($key, 'tokens', $newTokens - 1);
$redis->hSet($key, 'last_time', $now);
$redis->expire($key, 3600);
$redis->exec();

使用文件系统实现简单计数

对于小型应用,可以使用文件系统记录IP访问次数:

$ip = $_SERVER['REMOTE_ADDR'];
$limit = 100; // 每小时限制
$file = "ratelimit_$ip.txt";
$current = file_exists($file) ? (int)file_get_contents($file) : 0;

if ($current >= $limit) {
    header('HTTP/1.1 429 Too Many Requests');
    exit;
}

file_put_contents($file, $current + 1);

使用数据库存储访问记录

MySQL数据库方案适合需要持久化存储的场景:

$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$ip = $_SERVER['REMOTE_ADDR'];
$window = 60; // 60秒窗口
$limit = 30; // 30次请求

$stmt = $pdo->prepare("SELECT COUNT(*) FROM access_log 
                      WHERE ip = ? AND timestamp > DATE_SUB(NOW(), INTERVAL ? SECOND)");
$stmt->execute([$ip, $window]);
$count = $stmt->fetchColumn();

if ($count >= $limit) {
    header('HTTP/1.1 429 Too Many Requests');
    exit;
}

$pdo->prepare("INSERT INTO access_log (ip, timestamp) VALUES (?, NOW())")->execute([$ip]);

使用APCu内存缓存

APCu提供快速的进程内缓存,适合单服务器环境:

if (!extension_loaded('apcu')) {
    die('APCu extension required');
}

$ip = $_SERVER['REMOTE_ADDR'];
$key = "rl_$ip";
$limit = 50; // 每分钟50次
$window = 60; // 60秒

$count = apcu_fetch($key, $success);
if (!$success) {
    apcu_store($key, 1, $window);
} elseif ($count < $limit) {
    apcu_inc($key);
} else {
    header('HTTP/1.1 429 Too Many Requests');
    exit;
}

Nginx层限流配置

在Web服务器层面实现限流更高效,Nginx配置示例:

http {
    limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;

    server {
        location / {
            limit_req zone=ip_limit burst=20 nodelay;
        }
    }
}

响应头返回限流信息

良好的API设计应包含限流信息在响应头中:

php实现ip限流

header('X-RateLimit-Limit: 100');
header('X-RateLimit-Remaining: '.(100 - $count));
header('X-RateLimit-Reset: '.$resetTime);

选择具体方案时应考虑应用规模、性能要求和基础设施。分布式系统需要Redis或专业API网关,小型应用可采用文件或数据库方案。

标签: phpip
分享给朋友:

相关文章

php实现websocket

php实现websocket

PHP 实现 WebSocket WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议。PHP 可以通过多种方式实现 WebSocket 功能,以下是几种常见的方法: 使用 Ratc…

php实现

php实现

PHP 实现的基本方法 PHP 是一种服务器端脚本语言,广泛用于 Web 开发。以下是 PHP 实现的一些常见方法。 变量与数据类型 PHP 变量以 $ 开头,支持多种数据类型: $nam…

php实现注册

php实现注册

注册功能实现步骤 数据库准备 创建用户表,包含字段如id、username、password、email等。示例SQL: CREATE TABLE users ( id INT AUTO_I…

php 购物车实现

php 购物车实现

数据库设计 购物车功能通常需要设计数据库表存储商品和用户信息。常见的表包括products(商品表)、users(用户表)和cart(购物车表)。cart表通常包含字段:id(主键)、user_id(…

php无限分类的实现

php无限分类的实现

PHP无限分类的实现 无限分类是一种常见的树形结构数据组织方式,适用于商品分类、菜单管理、地区选择等场景。以下是几种实现方法: 递归实现法 递归是最直观的实现方式,通过函数自身调用来遍历子分类。数据…

php数据库实现

php数据库实现

PHP 连接 MySQL 数据库 使用 mysqli 扩展连接 MySQL 数据库: <?php $servername = "localhost"; $username = "usernam…