Hướng dẫn nâng cấp 1.5

Trước khi nâng cấp, vui lòng sao lưu và thực hiện lệnh sau:
composer require workerman/webman-framework ^1.5 -W && composer require webman/console ^1.2.12 && php webman install

Tính năng và thay đổi

Hỗ trợ workerman v5 coroutines

Lưu ý
workerman v5 yêu cầu PHP>=8.1
Lệnh nâng cấp workerman composer require workerman/workerman ^5.0.0 -W
Fiber coroutines cần cài đặt composer require revolt/event-loop ^1.0.0

Ví dụ

Phản hồi trễ

<?php

namespace app\controller;

use support\Request;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        // Ngủ 1.5 giây
        Timer::sleep(1.5);
        return $request->getRemoteIp();
    }
}

Timer::sleep() tương tự như hàm sleep() có sẵn trong PHP, khác biệt là Timer::sleep() không chặn tiến trình.

Gửi yêu cầu HTTP

Chú ý
Cần cài đặt composer require workerman/http-client ^2.0.0

<?php

namespace app\controller;

use support\Request;
use Workerman\Http\Client;

class TestController
{
    public function index(Request $request)
    {
        static $client;
        $client = $client ?: new Client();
        $response = $client->get('http://example.com'); // Gửi yêu cầu bất đồng bộ ở dạng đồng bộ
        return $response->getBody()->getContents();
    }
}

Tương tự, yêu cầu $client->get() là không chặn, điều này có thể được sử dụng để xử lý yêu cầu HTTP không chặn trong webman, nâng cao hiệu suất.

Xem thêm tại workerman/http-client

Thêm lớp support\Context

Lớp support\Context được sử dụng để lưu trữ dữ liệu liên quan đến yêu cầu; khi yêu cầu hoàn tất, dữ liệu ngữ cảnh tương ứng sẽ tự động xóa. Nghĩa là tuổi thọ của dữ liệu ngữ cảnh tuần tự với tuổi thọ của yêu cầu.

Ô nhiễm biến toàn cục

Môi trường coroutine cấm lưu trữ thông tin trạng thái liên quan đến yêu cầu trong biến toàn cục hoặc biến tĩnh, vì điều này có thể dẫn đến ô nhiễm biến toàn cục, ví dụ

<?php

namespace app\controller;

use support\Request;
use Workerman\Timer;

class TestController
{
    protected static $name = '';

    public function index(Request $request)
    {
        static::$name = $request->get('name');
        Timer::sleep(5);
        return static::$name;
    }
}

Thiết lập số tiến trình là 1, khi chúng ta gửi liên tiếp hai yêu cầu
http://127.0.0.1:8787/test?name=lilei
http://127.0.0.1:8787/test?name=hanmeimei
Chúng ta mong đợi kết quả trả về từ hai yêu cầu lần lượt là lileihanmeimei, nhưng thực tế, cả hai kết quả đều là hanmeimei.
Điều này xảy ra vì yêu cầu thứ hai ghi đè biến tĩnh $name, khi yêu cầu đầu tiên kết thúc ngủ, biến tĩnh $name đã trở thành hanmeimei.

Cách làm đúng là sử dụng ngữ cảnh lưu trữ dữ liệu trạng thái yêu cầu

<?php

namespace app\controller;

use support\Request;
use support\Context;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        Context::set('name', $request->get('name'));
        Timer::sleep(5);
        return Context::get('name');
    }
}

Biến cục bộ không gây ô nhiễm dữ liệu

<?php

namespace app\controller;

use support\Request;
use support\Context;
use Workerman\Timer;

class TestController
{
    public function index(Request $request)
    {
        $name = $request->get('name');
        Timer::sleep(5);
        return $name;
    }
}

$name là biến cục bộ, các coroutine không thể truy cập vào biến cục bộ của coroutine khác, vì vậy sử dụng biến cục bộ là an toàn cho coroutine.

Về coroutine

Coroutine không phải là giải pháp tối ưu, sử dụng coroutine đồng nghĩa với việc cần chú ý đến vấn đề ô nhiễm biến toàn cục/biến tĩnh và cần thiết lập ngữ cảnh. Hơn nữa, gỡ lỗi trong môi trường coroutine phức tạp hơn so với lập trình chặn.

Lập trình chặn trong webman thực sự đủ nhanh, dựa trên dữ liệu kiểm tra từ techempower.com, trong vòng ba năm qua, hiệu suất xử lý cơ sở dữ liệu của webman vượt gấp đôi so với framework web go gin, echo, gần 40 lần so với framework truyền thống Laravel.

Khi cả cơ sở dữ liệu và redis đều nằm trong mạng nội bộ, lập trình chặn có thể thường cao hơn so với coroutine, điều này là do khi cơ sở dữ liệu, redis đủ nhanh, chi phí tạo, lên lịch và huỷ coroutine có thể lớn hơn chi phí chuyển đổi tiến trình. Do đó, việc triển khai coroutine không nhất thiết làm cho hiệu suất nổi bật.

Khi nào sử dụng coroutine

Khi doanh nghiệp có yêu cầu trả chậm, ví dụ như khi doanh nghiệp cần truy cập vào API bên thứ ba, có thể sử dụng workerman/http-client để gửi yêu cầu HTTP bất đồng bộ theo cách coroutine, nâng cao khả năng xử lý đồng thời của ứng dụng.