Xử lý nghiệp vụ chậm
Đôi khi chúng ta cần xử lý các nghiệp vụ chậm, để tránh ảnh hưởng đến các yêu cầu xử lý khác của webman, các nghiệp vụ này có thể được xử lý bằng các giải pháp khác nhau tùy thuộc vào từng trường hợp.
Giải pháp 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ý nghiệp vụ đột biến lớn.
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 kết hợp với các dịch vụ khác, ví dụ như sử dụng webman/push để đẩy kết quả xử lý.
Giải pháp 2 Thêm cổng HTTP
Thêm cổng HTTP để xử lý các yêu cầu chậm, các yêu cầu chậm này sẽ được chuyển đến một nhóm tiến trình cụ thể thông qua cổng này và kết quả sẽ được trả trực tiếp về cho khách hàng.
Ưu điểm
Có thể trực tiếp trả dữ liệu về cho khách hàng.
Nhược điểm
Không thể xử lý các yêu cầu đột biến lớn.
Các bước thực hiện
Thêm cấu hình sau vào config/process.php
.
return [
// ... 这里省略了其它配置 ...
'task' => [
'handler' => \Webman\App::class,
'listen' => 'http://0.0.0.0:8686',
'count' => 8, // 进程数
'user' => '',
'group' => '',
'reusePort' => true,
'constructor' => [
'requestClass' => \support\Request::class, // request类设置
'logger' => \support\Log::channel('default'), // 日志实例
'appPath' => app_path(), // app目录位置
'publicPath' => public_path() // public目录位置
]
]
];
Vậy nên các giao diện chậm có thể đi qua nhóm tiến trình http://127.0.0.1:8686/
, không ảnh hưởng đến việc xử lý nghiệp vụ của các tiến trình khác.
Để cho phía trước không cảm nhận sự khác biệt giữa các cổng, có thể thêm một proxy đến cổng 8686 trong nginx. Giả sử các đường dẫn yêu cầu của giao diện chậm đều bắt đầu bằng /tast
, toàn bộ cấu hình nginx sẽ tương tự như sau:
upstream webman {
server 127.0.0.1:8787;
keepalive 10240;
}
# Thêm một upstream 8686
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 /tast đi qua cổng 8686, hãy thay đổi /tast thành tiền tố bạn cần dựa trên tình hình thực tế
location /tast {
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
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;
}
}
}
Vậy nên khi khách hàng truy cập domain.com/tast/xxx
, yêu cầu sẽ được xử lý bởi cổng 8686 riêng biệt, không ảnh hưởng đến việc xử lý yêu cầu của cổng 8787.
Giải pháp 3 Sử dụng http chunked gửi dữ liệu không đồng bộ
Ưu điểm
Có thể trả dữ liệu trực tiếp về 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('')); // 发送空的的chunk代表response结束
});
// 先发送一个http头,后续数据通过异步发送
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
Ghi chú
Ví dụ này sử dụng khách hàngworkerman/http-client
để lấy kết quả http một cách không đồng bộ và trả về dữ liệu, bạn cũng có thể sử dụng các khách hàng không đồng bộ khác như AsyncTcpConnection.