Aggregating High‑Concurrency Requests with Swoole Coroutine in PHP
This tutorial explains how to improve high‑concurrency order processing by aggregating requests and using batch inserts with Swoole coroutines in PHP, illustrating the concept with elevator‑like logic and a complete code example.
The article introduces a technique for handling high‑concurrency order creation by aggregating incoming requests and performing batch INSERT operations, which can significantly improve database efficiency compared to inserting each order individually.
It draws an analogy to an elevator: filling the elevator before moving up reduces traffic, similar to collecting multiple requests before executing a single batch insert.
A complete PHP example using Swoole coroutine is provided. The code enables coroutine runtime, defines constants for maximum retries, batch size, and timeout, creates a channel to hold pending requests, and implements a coroutine that collects requests, validates them, builds a batch INSERT SQL statement, and executes it.
The request handler pushes incoming HTTP POST data into the channel with a timeout, and the response logic returns either a timestamp on success or an error/timeout message based on the processing result.
<?php
Swoole\Runtime::enableCoroutine($flags = SWOOLE_HOOK_ALL);
// Maximum retry attempts
const MAX_TIMES = 10;
// Maximum pending requests per batch
const MAX_REQUEST = 3;
// Server timeout to avoid endless waiting
const MAX_TIMEOUT = 5;
Co\run(function () {
// Channel for request transmission; avoids sharing global variables across coroutines
$rqChannel = new Swoole\Coroutine\Channel(MAX_REQUEST);
// Simulated order creation coroutine
$createOrder = function () use ($rqChannel) {
$rqQueue = [];
$times = MAX_TIMES;
while (true) {
$times--;
$rq = $rqChannel->pop(1);
if (!empty($rq)) {
$rqQueue[] = $rq;
}
if ($times > 0 && count($rqQueue) < MAX_REQUEST) {
continue;
}
$times = MAX_TIMES;
$sql = "INSERT INTO orders VALUES ";
$inserts = [];
$validator = function ($input): bool {
array_filter($input);
return true;
};
foreach ($rqQueue as $index => $rq) {
list($data, $chan) = $rq;
unset($rqQueue[$index]);
if ($chan->errCode === SWOOLE_CHANNEL_CLOSED) {
$data = null;
continue;
}
$bool = $validator($data);
if ($bool) {
$inserts[] = "({$data['user_name']}, {$data['amount']}, {$data['mobile']})";
$chan->push(['state' => 1]);
} else {
$chan->push(['state' => 0]);
}
}
$sql .= (implode(',', $inserts) . ';');
echo $sql;
}
};
go($createOrder);
// Route handler for order creation
$orderHandler = function ($rq, $res) use ($rqChannel) {
$chan = new Swoole\Coroutine\Channel(1);
$bool = $rqChannel->push([$rq->post, $chan], MAX_TIMEOUT);
if (!$bool) {
$chan->close();
$res->end('timeout');
}
if (!empty($data = $chan->pop())) {
$chan->close();
if ($data['state'] === 1) {
$res->end(microtime());
} else {
$res->end('error');
}
}
};
$server = new Co\Http\Server("0.0.0.0", 9502, false);
$server->handle('/order/create', $orderHandler);
$server->start();
});The surrounding text emphasizes that the $rqQueue variable acts like the elevator, holding requests until a batch is ready, and $times represents the waiting cycles. It also warns developers not to use shared memory for communication inside coroutine environments, preferring channel‑based communication.
In conclusion, the tutorial is aimed at beginners, with promises of more tutorials in the future and an invitation for readers to leave feedback.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
php Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
