Xử lý công việc chậm
Đôi khi chúng ta cần xử lý các công việc chậm để tránh ảnh hưởng đến việc xử lý các yêu cầu khác của webman. Tùy theo tình huống, các công việc này có thể sử dụng các phương án xử lý khác nhau.
Phương án 1: Sử dụng hàng đợi tin nhắn
Tham khảo hàng đợi Redis hàng đợi Stomp
Ưu điểm
Có thể xử lý các yêu cầu xử lý công việc lớn đột ngột
Nhược điểm
Không thể trả kết quả trực tiếp cho khách hàng. Nếu cần đẩy kết quả phải phối hợp với dịch vụ khác, ví dụ sử dụng webman/push để đẩy kết quả xử lý.
Phương án 2: Thêm cổng HTTP mới
Thêm cổng HTTP mới để xử lý các yêu cầu chậm. Những yêu cầu chậm này qua cổng này được một nhóm quy trình cụ thể xử lý, sau khi xử lý trả kết quả trực tiếp cho khách hàng.
Ưu điểm
Có thể trả dữ liệu trực tiếp cho khách hàng
Nhược điểm
Không thể xử lý các yêu cầu lớn đột ngột
Các bước thực hiện
Thêm cấu hình sau vào config/process.php.
return [
// ... Bỏ qua các cấu hình khác ở đây ...
'task' => [
'handler' => \Webman\App::class,
'listen' => 'http://0.0.0.0:8686',
'count' => 8, // Số lượng quy trình
'user' => '',
'group' => '',
'reusePort' => true,
'constructor' => [
'requestClass' => \support\Request::class, // Cài đặt lớp request
'logger' => \support\Log::channel('default'), // Thể hiện logger
'appPath' => app_path(), // Vị trí thư mục app
'publicPath' => public_path() // Vị trí thư mục public
]
]
];
Như vậy các giao diện chậm có thể đi qua nhóm quy trình tại http://127.0.0.1:8686/ mà không ảnh hưởng đến việc xử lý công việc của các quy trình khác.
Để giao diện người dùng không cảm nhận sự khác biệt về cổng, có thể thêm proxy tới cổng 8686 trong nginx. Giả sử đường dẫn yêu cầu giao diện chậm đều bắt đầu bằng /task, cấu hình nginx sẽ tương tự như sau:
upstream webman {
server 127.0.0.1:8787;
keepalive 10240;
}
# Thêm upstream 8686 mới
upstream task {
server 127.0.0.1:8686;
keepalive 10240;
}
server {
server_name webman.com;
listen 80;
access_log off;
root /path/webman/public;
# Các yêu cầu bắt đầu bằng /task đi qua cổng 8686, vui lòng thay đổi /task thành tiền tố cần thiết theo tình hình
location /task {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://task;
}
# Các yêu cầu khác đi qua cổng 8787 ban đầu
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Connection "";
if (!-f $request_filename){
proxy_pass http://webman;
}
}
}
Như vậy khi khách hàng truy cập domain.com/task/xxx sẽ được xử lý qua cổng 8686 riêng biệt, không ảnh hưởng đến việc xử lý yêu cầu cổng 8787.
Phương án 3: Sử dụng HTTP Chunked gửi dữ liệu phân đoạn bất đồng bộ
Ưu điểm
Có thể trả dữ liệu trực tiếp cho khách hàng
Cài đặt workerman/http-client
composer require workerman/http-client
app/controller/IndexController.php
<?php
namespace app\controller;
use support\Request;
use support\Response;
use Workerman\Protocols\Http\Chunk;
class IndexController
{
public function index(Request $request)
{
$connection = $request->connection;
$http = new \Workerman\Http\Client();
$http->get('https://example.com/', function ($response) use ($connection) {
$connection->send(new Chunk($response->getBody()));
$connection->send(new Chunk('')); // Gửi chunk rỗng biểu thị kết thúc phản hồi
});
// Gửi header HTTP trước, dữ liệu sau được gửi bất đồng bộ
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
Gợi ý
Ví dụ này sử dụng clientworkerman/http-clientđể lấy kết quả HTTP bất đồng bộ và trả dữ liệu. Cũng có thể sử dụng client bất đồng bộ khác như AsyncTcpConnection.