swoole实现http请求合并

发布于:2022-12-16 ⋅ 阅读:(264) ⋅ 点赞:(0)

在高并发的场景下,数据库压力剧增,为了减少并发对数据库造成的压力,服务器可实现HTTP请求合并

合并HTTP请求需要用到swoole协程channel

 

 // 代码实现

 protected function setChannelArr()
    {
        if ($this->channelArr === null) {
            $this->channelArr = new \Swoole\Coroutine\Channel(1);
        }
        if ($this->firstTime === null) {
            $this->firstTime = $this->msectime();
        }
    }

    protected function msectime()
    {
        list($msec, $sec) = explode(' ', microtime());
        $msectime = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
        return $msectime;
    }

    protected function getData()
    {

        $data = $this->channelArr->pop();
        echo "消费第pop次\n";
        return $data;

    }

    protected function clean()
    {
        $this->count = 0;
        $this->requestArr = [];
        $this->firstTime = null;
    }

  

    public function index(RequestInterface $request, ResponseInterface $response)
    {

        $keywords = $request->getQueryParams()['keywords'];
        if (!empty($keywords)) {


            $this->requestArr[] = $keywords;

            $this->count++;
            echo "第{$this->count}次请求\n";

            $this->setChannelArr();

            return $response->json(['data' => $this->getData()]);

        }
    }

    public function __construct()
    {
//        co(function () {

            swoole_timer_tick($this->timeOut, function () {


                if ($this->count === 0) {
                    return;
                }

                $currentTime = $this->msectime();
                echo "请求======================================\n";
                echo "首次访问:" . $this->firstTime . "\n";
                echo "时间差:" . $currentTime . "\n";

                if ($this->count > $this->maxTimes || $currentTime - $this->firstTime > $this->timeOut) {
                    echo "开始处理数据\n";
                    try {
                        $arr = GoodsAuto::whereIn('id', $this->requestArr)
                            ->select()->get()->toArray();

                        foreach ($this->requestArr as $key => $keywords) {
                            foreach ($arr as $v) {
                                if ($keywords == $v['id']) {
                                    echo "生产第{$key}次,值{$v['id']}\n";
                                    $this->channelArr->push($v);
                                    break;
                                }
                            }
                        }
                        $this->clean();
                    } catch (\Excetion $e) {
                        echo $e->getMessage();
                    }
                }
            });
//        });
    }