1.5 베타 버전 업그레이드 안내
백업을 수행한 후 다음 명령을 실행하여 업그레이드하십시오.
composer require workerman/webman-framework ^1.5 -W && composer require webman/console ^1.2.12 && php webman install
기능 및 변경 사항
workerman v5 펑션 지원
참고
workerman v5는 PHP>=8.1을 요구합니다
workerman 업그레이드 명령어composer require workerman/workerman ^5.0.0 -W
Fiber 펑션을 사용하려면composer require revolt/event-loop ^1.0.0
를 설치해야 합니다.
예시
지연 응답
<?php
namespace app\controller;
use support\Request;
use Workerman\Timer;
class TestController
{
public function index(Request $request)
{
// 1.5초 대기
Timer::sleep(1.5);
return $request->getRemoteIp();
}
}
Timer::sleep()
는 PHP의 내장 sleep()
함수와 유사하지만, Timer::sleep()
는 프로세스를 차단하지 않습니다.
HTTP 요청 보내기
주의
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'); // 비동기 방식으로 동기적으로 요청 보내기
return $response->getBody()->getContents();
}
}
$client->get()
요청도 비차단식입니다. 이것은 webman에서 비차단식으로 HTTP 요청을 처리하여 성능을 향상시킬 수 있습니다.
더 많은 정보는 workerman/http-client를 참고하세요.
support\Context 클래스 추가
support\Context 클래스는 요청 관련 데이터를 저장하는 데 사용됩니다. 요청이 완료되면 해당 컨텍스트 데이터가 자동으로 삭제됩니다. 즉, 컨텍스트 데이터 수명은 요청 수명을 따릅니다.
전역 변수 오염
펑션 환경에서는 요청 관련 상태 정보를 전역 변수나 정적 변수에 저장하면 안 됩니다. 그렇게 함으로써 전역 변수 오염이 발생할 수 있기 때문입니다. 예를 들어,
<?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;
}
}
프로세스 수를 1로 설정하고 연속적으로 두 개의 요청을 보낼 경우
http://127.0.0.1:8787/test?name=lilei
http://127.0.0.1:8787/test?name=hanmeimei
우리는 두 요청의 반환 결과가 각각 lilei
와 hanmeimei
일 것으로 기대하지만, 실제로 반환되는 것은 모두 hanmeimei
입니다.
이는 두 번째 요청이 정적 변수 $name
을 덮어쓰기 때문에 발생합니다. 첫 번째 요청이 대기를 마치고 반환될 때 정적 변수 $name
은 이미 hanmeimei
로 되어있기 때문입니다.
올바른 방법은 요청 상태 데이터를 context에 저장하는 것입니다
<?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');
}
}
로컬 변수는 데이터 오염을 일으키지 않습니다
<?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;
}
}
로컬 변수는 각 펑션 간에 서로 접근할 수 없으므로 안전합니다.
펑션에 대해
펑션은 마법인이 아닙니다. 펑션을 도입하는 것은 전역 변수/정적 변수 오염 문제 및 컨텍스트 설정에 유의해야 함을 의미합니다. 또한, 펑션 환경에서 버그를 디버그하는 것이 차단식 프로그래밍보다 조금 더 복잡합니다.
웹만 차단식 프로그래밍은 실제로 충분히 빠릅니다. techempower.com에서 최근 3년 동안의 벤치마크 데이터를 보면, 웹만의 차단식 프로그래밍은 데이터베이스 비즈니스가 포함된 경우 go의 웹 프레임워크 gin, echo 등의 성능보다 거의 두 배 높고 전통적인 프레임워크인 라라벨보다 거의 40배 높습니다.
데이터베이스, 레디스가 모두 내부 네트워크에 있을 때, 멀티 프로세스 차단식 프로그래밍 성능은 종종 펑션을 도입하더라도 성능이 급격히 향상되지 않을 수 있습니다. 왜냐하면 데이터베이스, 레디스 등이 충분히 빠를 때, 펑션을 생성, 예약 및 삭제하는 비용이 프로세스 전환 비용보다 더 클 수 있기 때문입니다. 따라서 이러한 상황에서 펑션 도입으로 성능을 현저히 향상시킬 수 없을 수 있습니다.
펑션을 사용하는 시기
비즈니스에 느린 요청이 있는 경우, 예를 들어 비즈니스가 외부 API에 접근해야 할 경우, workerman/http-client를 사용하여 비차단식으로 비동기 HTTP 호출을 시작함으로써 애플리케이션의 병행 능력을 향상시킬 수 있습니다.