当前位置:首页 > 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实现递归

php实现递归

递归的基本概念 递归是一种函数调用自身的技术,适用于解决可以分解为相同子问题的问题。在PHP中,递归需要明确的终止条件(基线条件),否则会导致无限循环。 递归实现阶乘 阶乘是经典的递归案例,n! =…

php 实现购物车

php 实现购物车

PHP 实现购物车功能 购物车功能是电子商务网站的核心部分,可以通过 PHP 和 Session 或数据库来实现。以下是两种常见的实现方式: 使用 Session 存储购物车数据 Sessi…

无限分类实现 php

无限分类实现 php

无限分类的实现方法 无限分类通常用于构建多层级结构的数据,如商品分类、部门架构等。以下是几种常见的实现方式: 邻接列表模式(Adjacency List) 邻接列表是最简单的实现方式,通过在每个记录…

php实现注册登录

php实现注册登录

PHP 注册功能实现 创建数据库表(以 MySQL 为例) CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, usern…

php实现域名

php实现域名

PHP实现域名操作的方法 获取当前域名 使用$_SERVER['HTTP_HOST']可以获取当前访问的域名: $currentDomain = $_SERVER['HTTP_HOST']; ech…

php 实现聊天功能

php 实现聊天功能

PHP 实现聊天功能的方法 使用 WebSocket 和 Ratchet 库 WebSocket 是实现实时聊天的理想选择。Ratchet 是一个 PHP 库,用于处理 WebSocket 连接。…