Implementing a PHP Coroutine Task Scheduler for Concurrent RPC and MySQL Access
This article presents a PHP coroutine‑based Task Scheduler that enables high‑concurrency RPC calls and asynchronous MySQL queries, explains its design and implementation with code examples, compares performance against traditional synchronous and HttpMultiClient approaches, and discusses task dependency handling using DAG and topological sorting.
With the rapid growth of user traffic, the existing PHP micro‑service architecture faces IO‑intensive challenges, requiring a solution that can issue many RPC and database requests concurrently without blocking.
The proposed solution adopts a lightweight coroutine model inspired by Go, wrapping the complexity of PHP generators and yield into a Composer package that developers can use to achieve concurrent RPC and MySQL access.
The core of the solution is a Task Scheduler model that maintains a queue of Task objects; each task runs until it yields, at which point it is re‑queued until completion, allowing many IO‑bound operations to progress in parallel.
Key scheduler code: public function run() { while (!$this->taskQueue->isEmpty()) { $task = $this->taskQueue->dequeue(); $task->run(); if ($task->isFinished()) { unset($this->taskMap[$task->getTaskId()]); } else { $this->schedule($task); } } } public function run($funcList) { if (empty($funcList)) return []; $scheduler = new Scheduler; foreach ($funcList as $func) { $scheduler->newTask($func()); } $scheduler->run($result); }
An example executor usage demonstrates creating ten anonymous functions that generate random numbers, yield between steps, and finally output the sum, illustrating how tasks are interleaved without waiting for each other:
$funcList = []; for ($i = 0; $i < 10; $i++) { $funcList[] = function () use ($i) { $a = random_int(0, 100); echo "task $i: generate a $a\n"; yield; $b = random_int(0, 100); echo "task $i: generate b $b\n"; yield; echo "task $i: " . ($a + $b) . "\n"; }; } $executor = new Executor(); $executor->run($funcList);
For RPC concurrency, the existing HttpClient based on Guzzle is refactored: a TsHttpClient inherits from it and provides asynchronous request methods ( getRequestAsync , postRequestAsync ) that are scheduled with yield , enabling non‑blocking batch RPC calls. Performance tests show the coroutine approach is slightly slower than Guzzle’s HttpMultiClient due to a two‑step request‑wait pattern.
MySQL asynchronous access is achieved via the mysqli extension with MYSQLI_ASYNC . A db class encapsulates connection handling, async queries, and result fetching using mysqli_poll . Sample coroutine functions ( f1 , f2 , f3 ) illustrate yielding the async query object and later fetching results, allowing multiple queries to run in parallel and reducing total execution time from >2 s to ~1 s.
class db { static $links; private $obj; function getConn() { /* ... */ } function async_query($sql) { $link = $this->getConn(); $link->query($sql, MYSQLI_ASYNC); return $link; } function fetch() { /* poll and reap */ } } function f1() { $db = new db(); $obj = $db->async_query('select sleep(1)'); yield $obj; $row = $db->fetch(); yield $row; }
An alternative “request‑self‑service” method wraps database queries into internal API calls, schedules them with the same coroutine scheduler, and aggregates results, offering a trade‑off between latency and additional internal request overhead.
When tasks have dependencies, they are modeled as a directed acyclic graph (DAG). Cycle detection is performed via depth‑first search, and a topological sort (Kahn’s algorithm) identifies independent tasks that can be executed concurrently, ensuring correct ordering without deadlocks.
In summary, the article explains the design, implementation, and performance evaluation of a PHP coroutine Task Scheduler that enables high‑concurrency RPC and MySQL operations, discusses dependency handling, and provides practical code snippets for integration into backend services.
Beike Product & Technology
As Beike's official product and technology account, we are committed to building a platform for sharing Beike's product and technology insights, targeting internet/O2O developers and product professionals. We share high-quality original articles, tech salon events, and recruitment information weekly. Welcome to follow us.
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.