PHP 实现服务限流控制

本文试图基于计数器实现一个简单服务限流程序,这个计数器的值表示服务器尚可可以接待的请求数量。假设服务器设定的 qps 为 500,那么我们每隔 2 ms(即 1 / qps)检查计数器的值,如果小于设定的最大请求数,就给计数器 + 1,否则什么都不做。当请求进来的时候,如果计数器大于 0,表示可以提供服务,这时计数器 - 1,执行服务。如果计数器等于0,则无法提供服务。

代码如下:

$http = new Swoole\Http\Server('0.0.0.0', 9501);

// 限流控制对象
$traffic = new Traffic();
$traffic->start();

$http->on('request', function ($request, $response) use ($traffic) {

    // 无法提供服务,直接返回
    if (! $traffic->canServe()) {
        $response->header("Content-Type", "text/html; charset=utf-8");
        $response->end("<h1>The Server is busy...</h1>");
        return;
    }

    // 执行主逻辑代码
    $app = new App($request, $response);
    $app->run();

});

$http->start();


/**
 * 主逻辑代码
 * Class App
 */
class App {

    private $request;
    private $response;

    public function __construct($request, $response)
    {
        $this->request = $request;
        $this->response = $response;
    }


    public function run()
    {
        /**
         * do something
         */
        $this->response->header("Content-Type", "text/html; charset=utf-8");
        $this->response->end("<h1>I am in service</h1>");
    }
}

/**
 * 限流控制类
 */
class Traffic {

    /**
     * @var Redis redis 客户端
     */
    private $redis;

    /**
     * @var int 每秒可处理的请求数
     */
    private $qps = 2;

    /**
     * @var int 待处理请求的最大容量
     */
    private $maximum_requests = 5;

    public function __construct()
    {
        $redis = new Redis();
        $redis->connect('127.0.0.1', 6379);
        $this->redis = $redis;
    }

    /**
     * 开启计时器
     */
    public function start()
    {
        $redis = $this->redis;
        $time_interval = floor(1000 / $this->qps);
        $maximum_requests = $this->maximum_requests;

        // 计时器
        Swoole\Timer::tick($time_interval, function() use ($redis, $maximum_requests) {
            $num = $redis->get('num');
            var_dump($num);
            if ($num < $maximum_requests) {
                $redis->incr('num');
            }
        });
    }

    /**
     * 是否可以为 1 个请求提供服务
     * @return bool
     */
    public function canServe(): bool
    {
        $num = $this->redis->get('num');
        if ($num > 0) {
        	// 计数器 - 1
            $this->redis->decr('num');
            return true;
        } else {
            return false;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值