Home > PHP Framework > Swoole > body text

High-concurrency instance sharing: Swoole efficiently implements business through aggregation of requests

青灯夜游
Release: 2022-05-17 10:00:51
Original
3524 people have browsed it

This article will share with you an example of Swoole's high-concurrency aggregation request, and introduce how to make full use of the batch processing of the database to implement business functions more efficiently through aggregation of requests in high-concurrency scenarios. This example is only used as a starting point, hoping to stimulate more in-depth thinking.

High-concurrency instance sharing: Swoole efficiently implements business through aggregation of requests

Recommended related video courses: " Tens of millions of data concurrency solutions (theoretical and practical) "

Share some high-concurrency interview questions: 15 PHP interview questions about high concurrency (summary)

The background selected for this example is the concurrent order business. Under normal circumstances, creating an order on the backend is a insert operation one by one. When concurrency is low, the database's insert operation can indeed maintain good efficiency, but when the number of requests increases, the database frequently performs a single insert This will make the overall efficiency of the order business lower (this article simply assumes that 1 order = 1insert).

Through the above description, it is actually easy to think of the areas that need optimization. Analogy to the scene of taking an elevator in real life: an elevator is filled and then goes up, which can relieve the pressure of people flow as quickly as possible.

Let’s simply implement our idea with code:

<?php

Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);

// 最大等待次数
const MAX_TIMES = 10;
// 按批处理时, 每一批的最大请求暂留数量
const MAX_REQUEST = 3;
// 服务端最大超时时间, 避免客户端一直等待
const MAX_TIMEOUT = 5;

Co\run(function () {
    // 请求传输的channel, 原因是不要在swoole的协程环境中, 使用多个协程修改同一个全局变量
    // 如果是golang, 当然是可以不定义这里的$rqChannel
    // 只需要简单的将下面的$rqQueue和$times定义为全局变量即可达到一样的效果
    // 但是最好的方式任然是是通过channel共享内存
    $rqChannel = new Swoole\Coroutine\Channel(MAX_REQUEST);

    // 模拟创建订单
    $createOrder = function () use ($rqChannel) {
        // 使用数组模拟请求暂留队列
        $rqQueue = [];
        // 使用等待次数模拟tick效果
        $times = MAX_TIMES;
        while (true) {
            $times--;
            // 必须带上timeout参数, 否则channel是阻塞的
            $rq = $rqChannel->pop(1);
            // 保存1个正常的请求数据
            if (!empty($rq)) {
                $rqQueue[] = $rq;
            }
            // 请求数量未达上限或者还有等待次数时, 提前进入下一次循环
            if ($times > 0 && count($rqQueue) < MAX_REQUEST) {
                continue;
            }
            // 重置等待次数
            $times = MAX_TIMES;
            // 初始化SQL
            $sql = "INSERT INTO orders VALUES ";
            $inserts = [];
            // 模拟数据验证
            $validator = function ($input): bool {
                // 为了缩减代码, 没有真的做数据验证的处理
                array_filter($input);
                return true;
            };
            // $rqQueue在协程上下文是并发安全的, 所以遍历时不用担心
            foreach ($rqQueue as $index => $rq) {
                list($data, $chan) = $rq;
                // 这里可以考虑后置执行, 原因是后面可以有一些补救逻辑
                unset($rqQueue[$index]);
                // 判断$chan是否关闭å
                if ($chan->errCode === SWOOLE_CHANNEL_CLOSED) {
                    $data = null;
                    continue;
                }
                $bool = $validator($data);
                if ($bool) {
                    $inserts[] = "({$data[&#39;user_name&#39;]}, {$data[&#39;amount&#39;]}, {$data[&#39;mobile&#39;]})";
                    $chan->push([&#39;state&#39; => 1]);
                } else {
                    $chan->push([&#39;state&#39; => 0]);
                }
                // unset($rqQueue[$index]);
            }
            $sql .= (implode(&#39;,&#39;, $inserts) . &#39;;&#39;);
            // 模拟创建订单落库的逻辑
            echo $sql;
        }
    };

    // 新手要注意这一句代码的位置, 原因是 $server->start() 之后的代码不会执行
    go($createOrder);

    // 路由处理器
    $orderHandler = function ($rq, $res) use ($rqChannel) {
        $chan = new Swoole\Coroutine\Channel(1);
        // 使用timeout参数模拟超时
        $bool = $rqChannel->push([$rq->post, $chan], MAX_TIMEOUT);
        if (!$bool) {
            // 关闭$chan
            $chan->close();
            $res->end(&#39;timeout&#39;);
        }
        if (!empty($data = $chan->pop())) {
            // 关闭$chan
            $chan->close();
            // 区分成功或失败状态再输出响应
            if ($data[&#39;state&#39;] === 1) {
                $res->end(microtime());
            } else {
                $res->end(&#39;error&#39;);
            }
        }
    };

    $server = new Co\Http\Server("0.0.0.0", 9502, false);

    $server->handle(&#39;/order/create&#39;, $orderHandler);
    // 当前协程容器的终点
    $server->start();
});
Copy after login

The code is still very easy to understand as a whole, Variables$rqQueue is the analogy of an elevator. The number of times a hold request has to wait for a certain period of time $times is analogous to the need for an elevator to wait for the flow of people to enter one after another. Of course, the most important thing I hope readers will pay attention to is: In a coroutine environment, do not use shared memory for communication, but use communication to share memory.

Recommended learning: swoole tutorial

The above is the detailed content of High-concurrency instance sharing: Swoole efficiently implements business through aggregation of requests. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!