Coroutines
Coroutines là một cơ chế đồng thời cấp người dùng nhẹ hơn so với luồng, có khả năng thực hiện lập lịch đa nhiệm trong quá trình. Nó thực hiện việc chuyển đổi giữa các coroutine bằng cách điều khiển thủ công việc tạm ngừng và khôi phục, tránh được chi phí chuyển đổi ngữ cảnh quá trình.
Workerman cung cấp một giao diện coroutine chung, tự động tương thích với các trình điều khiển Swoole/Swow/Fiber ở tầng dưới.
Ghi chú
Tính năng này yêu cầu workerman>=5.1.0
Lưu ý
- Coroutines chỉ hỗ trợ trình điều khiển
SwooleSwowFiber - Nếu sử dụng trình điều khiển
Fiber, cần cài đặtcomposer require revolt/event-loop - Trình điều khiển
SwoolehoặcSwowcó thể tự động chuyển đổi các hàm chặn PHP thành coroutine, từ đó cho phép mã đồng bộ trước đó thực thi không đồng bộ - Tuy nhiên,
Fiberkhông thể tự động chuyển đổi nhưSwoolevàSwow, khi gặp các hàm chặn tích hợp sẵn của PHP sẽ chặn toàn bộ quá trình, sẽ không có chuyển đổi coroutine - Khi sử dụng các trình điều khiển
SwooleSwowFiber,workermantự động tạo một coroutine để thực thi mỗi khi chạy các callback nhưonWorkerStartonMessageonConnectonClosev.v. - Có thể sử dụng
$worker->eventLoop=xxx;để thiết lập các trình điều khiển coroutine khác nhau cho cácworkerkhác nhau
<?php
use Workerman\Connection\TcpConnection;
use Workerman\Coroutine;
use Workerman\Events\Swoole;
use Workerman\Events\Fiber;
use Workerman\Protocols\Http\Request;
use Workerman\Worker;
require_once __DIR__ . '/vendor/autoload.php';
$worker1 = new Worker('http://0.0.0.0:8001');
$worker1->eventLoop = Swoole::class; // Sử dụng coroutine Swoole
$worker1->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
$worker2 = new Worker('http://0.0.0.0:8001');
$worker2->eventLoop = Fiber::class; // Sử dụng coroutine Fiber tích hợp sẵn
$worker2->onMessage = function (TcpConnection $connection, Request $request) {
Coroutine::create(function () {
echo file_get_contents("http://www.example.com/event/notify");
});
$connection->send('ok');
};
Worker::runAll();
Giao diện mà coroutine cung cấp
interface CoroutineInterface
{
/**
* Tạo coroutine và ngay lập tức thực thi
*/
public static function create(callable $callable, ...$data): CoroutineInterface;
/**
* Bắt đầu chạy coroutine
*/
public function start(mixed ...$args): mixed;
/**
* Khôi phục việc chạy của coroutine
*/
public function resume(mixed ...$args): mixed;
/**
* Lấy id của coroutine
*/
public function id(): int;
/**
* Thiết lập callback khi hủy bỏ coroutine
*/
public static function defer(callable $callable): void;
/**
* Tạm dừng coroutine hiện tại
*/
public static function suspend(mixed $value = null): mixed;
/**
* Lấy coroutine hiện tại
*/
public static function getCurrent(): CoroutineInterface|Fiber|SwowCoroutine|static;
/**
* Kiểm tra xem hiện tại có phải là môi trường coroutine không
*/
public static function isCoroutine(): bool;
}
Về coroutine
Ưu điểm
Lợi ích lớn nhất khi PHP giới thiệu coroutine là có thể viết mã bất đồng bộ theo cách đồng bộ, tránh được địa ngục callback, cải thiện tính đọc và bảo trì của mã.
Coroutines có thể nâng cao tính linh hoạt của các tác vụ tập trung vào IO, cho phép sử dụng ít tiến trình hơn để cung cấp thông lượng lớn hơn.
Nhược điểm
Tuy nhiên, khi giới thiệu coroutine, các nhà phát triển cần thường xuyên chú ý đến ô nhiễm biến toàn cục, cạnh tranh tài nguyên, cải tiến thư viện bên thứ ba và các vấn đề khác, làm gia tăng chi phí bảo trì phát triển, gánh nặng tâm lý rõ rệt.
Việc giới thiệu coroutine tạo ra các chi phí bổ sung như tạo, lập lịch, huỷ, kết nối hồ bơi coroutine.
Theo dữ liệu kiểm tra hiệu suất, trong khi tận dụng tối đa CPU, việc giới thiệu coroutine dẫn đến hiệu suất cực hạn giảm khoảng 10%-20% so với IO chặn.