느린 작업 처리
가끔 우리는 느린 작업을 처리해야 할 필요가 있습니다. 느린 작업이 webman의 다른 요청 처리에 영향을 미치지 않도록 하기 위해, 이런 작업은 상황에 따라 다른 처리 방안을 사용할 수 있습니다.
방안 1 메시지 큐 사용
장점
폭발적으로 발생하는 대량의 작업 요청을 처리할 수 있습니다.
단점
결과를 클라이언트에 직접 반환할 수 없습니다. 결과를 푸시해야 할 경우, 다른 서비스와 결합해야 합니다. 예를 들어 webman/push를 사용하여 처리 결과를 푸시할 수 있습니다.
방안 2 HTTP 포트 추가
느린 요청을 처리하기 위해 새로운 HTTP 포트를 추가합니다. 이 느린 요청은 이 포트를 통해 특정한 프로세스 그룹에 들어가서 처리되며, 처리 후 결과를 클라이언트에 직접 반환합니다.
장점
데이터를 클라이언트에 직접 반환할 수 있습니다.
단점
폭발적인 대량 요청을 처리할 수 없습니다.
실행 단계
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 디렉터리 위치
]
]
];
이렇게 느린 인터페이스는 http://127.0.0.1:8686/
이 프로세스를 통해 실행될 수 있으며, 다른 프로세스의 작업 처리에 영향을 미치지 않습니다.
프론트엔드가 포트의 차이를 인식하지 않도록 하기 위해 nginx에 8686 포트로의 프록시를 추가할 수 있습니다. 예를 들어 느린 인터페이스의 요청 경로가 모두 /tast
로 시작한다고 가정할 때, 전체 nginx 구성은 다음과 유사합니다:
upstream webman {
server 127.0.0.1:8787;
keepalive 10240;
}
# 8686 포트의 upstream 추가
upstream task {
server 127.0.0.1:8686;
keepalive 10240;
}
server {
server_name webman.com;
listen 80;
access_log off;
root /path/webman/public;
# /tast로 시작하는 요청이 8686 포트를 거치도록 설정, /tast를 실제 필요에 따라 변경하세요.
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;
}
# 나머지 요청은 원래 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;
}
}
}
이렇게 클라이언트가 도메인.com/tast/xxx
에 접근하면 별도의 8686 포트를 통해 처리되고, 8787 포트의 요청 처리에 영향을 미치지 않습니다.
방안 3 http chunked를 이용한 비동기 청크 데이터 전송
장점
데이터를 클라이언트에 직접 반환할 수 있습니다.
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('')); // 빈 청크 전송으로 response 종료
});
// 먼저 http 헤더를 전송하고, 이후 데이터는 비동기로 전송
return response()->withHeaders([
"Transfer-Encoding" => "chunked",
]);
}
}
提示
본 예제에서는workerman/http-client
클라이언트를 사용하여 비동기적으로 http 결과를 가져오고 데이터를 반환하였습니다. 다른 비동기 클라이언트(예: AsyncTcpConnection)도 사용할 수 있습니다.