>  기사  >  백엔드 개발  >  Swoole 사용자 정의 프로젝트 초기화 이벤트 처리 구현 방법(코드)

Swoole 사용자 정의 프로젝트 초기화 이벤트 처리 구현 방법(코드)

不言
不言원래의
2018-09-13 17:01:151807검색

이 글의 내용은 Swoole 커스텀 프로젝트 초기화 이벤트 처리(코드)를 구현하는 방법에 대한 내용입니다. 필요한 친구들이 참고하시면 좋을 것 같습니다.

최근 Swoole을 기반으로 개발된 imi 프레임워크를 사용하여 프로젝트를 개발하다가 프로젝트 초기화 처리를 해야 한다는 요구사항이 발생했습니다. 초기화 프로세스가 완료되기 전에 Swoole이 요청을 처리하는 것을 원하지 않습니다. 일부 로드되지 않은 값이 있을 수 있으므로 요청 처리에 문제가 발생할 가능성이 높습니다.

문제 해결을 위한 사고 과정과 데모 코드는 아래와 같습니다.

우선 분석 후 Swoole은 다중 프로세스 모드로 실행되며 Master, Manager, Worker 프로세스로 구분됩니다.

마스터 프로세스는 서비스를 시작하는 cli 명령 파일이 위치한 프로세스입니다. 여기서 로드된 모든 클래스와 전역 변수는 다른 Worker 프로세스에서 사용할 수 없으며 초기화에 문제가 있습니다. 적용하려면 다시 시작해야 합니다.

Manager 프로세스의 상황은 기본적으로 위와 동일합니다.

그러면 Worker 프로세스만 처리를 하는데, WorkerStart 이벤트에 쓰면 각 Worker 프로세스가 이를 실행하게 됩니다.

WorkerStart 이벤트 정의:

function onWorkerStart(swoole_server $server, int $worker_id);
$worker_id는 이 작업자 프로세스의 ID를 나타내는 0-$worker_num 사이의 숫자입니다.

그렇다면 이것은 처리하기 쉽고 직접 판단합니다. 작업자 ID 프로젝트 초기화 이벤트를 트리거하려면 0입니다. 남은 질문은 초기화 실행이 완료될 때까지 모든 작업자 프로세스가 요청을 처리하지 못하도록 하는 방법입니다.

고민하고 시도해본 후, 이 문제는 코루틴을 걸면 해결될 수 있습니다. 데모 코드는 다음과 같습니다.

<?php

use Swoole\Coroutine;

$http = new swoole_http_server(&#39;127.0.0.1&#39;, 8080);

$http->on(&#39;WorkerStart&#39;, function(swoole_http_server $server, $workerId){
    $initFlagFile = __DIR__ . &#39;/init.flag&#39;;
    if(0 === $server->worker_id && (!is_file($initFlagFile) || file_get_contents($initFlagFile) != $server->manager_pid))
    {
        // 处理项目初始化事件
        initApp();
        // 写入文件,保证不再重复触发项目初始化事件
        file_put_contents($initFlagFile, $server->manager_pid);
        // 当前worker进程恢复协程
        resumeCos();
        // 通知其它worker进程
        for($i = 1; $i < $server->setting[&#39;worker_num&#39;]; ++$i)
        {
            $server->sendMessage(&#39;init&#39;, $i);
        }
    }
});

$http->on(&#39;PipeMessage&#39;, function(swoole_http_server $server, $srcWorkerId, $data) {
    if(0 === $srcWorkerId && &#39;init&#39; === $data && !defined(&#39;APP_INITED&#39;))
    {
        // 其它worker进程恢复协程
        resumeCos();
    }
});

$http->on(&#39;request&#39;, function (swoole_http_request $request, swoole_http_response $response) {
    // 判断未初始化完毕,则挂起协程
    if(!defined(&#39;APP_INITED&#39;))
    {
        $GLOBALS[&#39;WORKER_START_END_RESUME_COIDS&#39;][] = Coroutine::getuid();
        Coroutine::suspend();
    }
    $response->header(&#39;content-type&#39;, &#39;text/html;charset=utf-8&#39;);
    $response->end(&#39;IMI 是一款基于 Swoole 开发的协程 PHP 开发框架,拥有常驻内存、协程异步非阻塞IO等优点。官方网站:<a href="https://imiphp.com" target="_blank">https://imiphp.com</a>&#39;);
});

$http->start();

/**
 * 处理项目初始化事件,比如这里延时5秒,模拟初始化处理
 *
 * @return void
 */
function initApp()
{
    $count = 5;
    for($i = 0; $i < $count; ++$i)
    {
        echo &#39;initing &#39;, ($i + 1), &#39;/&#39;, $count, PHP_EOL;
        sleep(1);
    }
}

/**
 * 恢复协程
 *
 * @return void
 */
function resumeCos()
{
    define(&#39;APP_INITED&#39;, true);
    $coids = $GLOBALS[&#39;WORKER_START_END_RESUME_COIDS&#39;] ?? [];
    fwrite(STDOUT, &#39;suspend co count: &#39; . count($coids) . PHP_EOL);
    foreach($coids as $id)
    {
        Coroutine::resume($id);
    }
}

초기화가 완료되었는지 판단하면 됩니다. 초기화되지 않은 경우 요청 이벤트 완료되면 현재 코루틴이 일시 중지되고 코루틴 ID가 전역 변수에 추가됩니다.

0번째 작업자 프로세스가 초기화를 완료하면 초기화 기간 동안 들어온 요청이 이때 다른 작업자 프로세스에 메시지를 보내 일시 중단된 코루틴을 깨웁니다.

관련 권장사항:

사용자 정의 events_javascript 기술의 javascript 구현에 대한 자세한 설명

#🎜 🎜#프로젝트에서 Angularjs 사용자 정의 지침을 사용하는 방법

위 내용은 Swoole 사용자 정의 프로젝트 초기화 이벤트 처리 구현 방법(코드)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.