Home  >  Article  >  PHP Framework  >  Try how to change Laravel to Swoole version

Try how to change Laravel to Swoole version

藏色散人
藏色散人forward
2022-12-02 16:29:021186browse

This article will give you relevant knowledge about Laravel and Swoole. The main content is to teach you how to change Laravel to the Swoole version (try to learn, it is not recommended to change the existing project). Let’s take a look together. I hope it will be helpful to everyone. Helped!

Preface

It is not recommended to use in production environment

Create a new laravel project

laravel new swoole-laravel

Change Laravel to Swoole version

Create a swoole_server.php file in the root directory of Laravel, and then copy the code in public/index.php over [Recommended learning: laravel video tutorial

<?php
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
define(&#39;LARAVEL_START&#39;, microtime(true));
require __DIR__.&#39;/../vendor/autoload.php&#39;;
$app = require_once __DIR__.&#39;/../bootstrap/app.php&#39;;
$kernel = $app->make(Kernel::class);
$response = $kernel->handle(
    $request = Request::capture()
)->send();
$kernel->terminate($request, $response);

In the first step, the loading of the framework file is certain, and it should be loaded in the main process. There is no need for sub-processes or coroutines to load it repeatedly. Therefore, the require above does not need to be touched.

The second step is to start an HTTP Swoole service. This has been mentioned many times before. Note that in onRequest, we should put the $kernel related code in it.

$http = new Swoole\Http\Server(&#39;0.0.0.0&#39;, 9501);
$http->on(&#39;Request&#39;, function ($req, $res) use($app) {
    try {
        $kernel = $app->make(Kernel::class);
        $response = $kernel->handle(
            $request = Request::capture()
        )->send();
        $kernel->terminate($request, $response);
    }catch(\Exception $e){
        print_r($e->getMessage());
    }
});
echo "服务启动", PHP_EOL;
$http->start();

Is this enough? Why don't you give it a try first. Under normal circumstances, you may not be able to obtain any input or output. Why is this?

The third step is to solve the input problem. In fact, super global variables do not work in Swoole, so variables such as $_GET will become invalid, and Request-related objects in Laravel will not be able to obtain data. What to do about this? We just get this data from the parameters of onRequest and then put it back into $_GET in the current process coroutine.

$http->on(&#39;Request&#39;, function ($req, $res) use($app) {
    $_SERVER = [];
    if(isset($req->server)){
        foreach($req->server as $k => $v){
            $_SERVER[strtoupper($k)] = $v;
        }
    }
    $_GET = [];
    if(isset($req->get)){
        foreach ($req->get as $k => $v){
            $_GET[$k] = $v;
        }
    }
    $_POST = [];
    if(isset($req->post)){
        foreach ($req->post as $k => $v){
            $_POST[$k] = $v;
        }
    }
    try {
        $kernel = $app->make(Kernel::class);
        $response = $kernel->handle(
            $request = Request::capture()
        )->send();
        $kernel->terminate($request, $response);
    }catch(\Exception $e){
        print_r($e->getMessage());
    }
});

The above three pieces of code solve the problems of $_SERVER, $_GET and $_POST respectively. Now if you try again, the parameters can be received, but why is the output printed on the console?

The fourth step is to solve the output problem, put all the output in the frame into the output buffer, and then use Swoole's Response to return.

$http->on(&#39;Request&#39;, function ($req, $res) use($app) {
    $_SERVER = [];
    if(isset($req->server)){
        foreach($req->server as $k => $v){
            $_SERVER[strtoupper($k)] = $v;
        }
    }
    $_GET = [];
    if(isset($req->get)){
        foreach ($req->get as $k => $v){
            $_GET[$k] = $v;
        }
    }
    $_POST = [];
    if(isset($req->post)){
        foreach ($req->post as $k => $v){
            $_POST[$k] = $v;
        }
    }
    //把返回放到一个缓冲区里
    ob_start();
    try {
        $kernel = $app->make(Kernel::class);
        $response = $kernel->handle(
            $request = Request::capture()
        )->send();
        $kernel->terminate($request, $response);
    }catch(\Exception $e){
        print_r($e->getMessage());
    }
    $ob = ob_get_contents();
    ob_end_clean();
    $res->end($ob);
});

The last ob_start () content is also what we have studied before, so we won’t explain it further.

All code

start();

At this point, our simplest framework transformation is completed, let’s try the effect quickly.

Run

php swoole_server.php

Access

http://47.113.xxx.xx:9501/

Try the coroutine effect

First define a route. Or we can directly modify the default route.

Route::get(&#39;/&#39;, function () {
    echo Swoole\Coroutine::getCid(), "<br/>";
    print_r(Swoole\Coroutine::stats());
    Swoole\Coroutine::sleep(10);
    echo "<br/>";
    echo getmypid(), "<br/>";
//    return view(&#39;welcome&#39;);
});

Printed a bunch of things, but they should all be familiar. The first two are the output of coroutine ID and coroutine information, and then we Swoole\Coroutine::sleep () for 10 seconds, and then print Here is the process ID.

Then we open the browser and prepare to access the two tabs together.

// 第一个访问的页面
1
Array
(
    [event_num] => 2
    [signal_listener_num] => 0
    [aio_task_num] => 0
    [aio_worker_num] => 0
    [aio_queue_size] => 0
    [c_stack_size] => 2097152
    [coroutine_num] => 1
    [coroutine_peak_num] => 1
    [coroutine_last_cid] => 1
)
1468
// 第二个访问的页面
2
Array
(
    [event_num] => 2
    [signal_listener_num] => 0
    [aio_task_num] => 0
    [aio_worker_num] => 0
    [aio_queue_size] => 0
    [c_stack_size] => 2097152
    [coroutine_num] => 2
    [coroutine_peak_num] => 2
    [coroutine_last_cid] => 2
)
1468

Do you see it? Each onRequest event actually opens a new coroutine to handle the request, so their coroutine IDs are different. At the same time, the second request will not wait until 20 seconds to return because the first request is blocked. Finally, in the coroutine status, we also see that there are two coroutine_nums displayed in the second request, indicating that there are currently two coroutines processing tasks. In the end, the processes are the same, they all follow the same process.

Try the multi-process effect

By default, the above code is a main process and a Worker process, and then uses the coroutine capability. In fact, this effect can instantly kill the ordinary PHP-FPM effect. But we need to make full use of the performance of multi-core machines, that is to say, we enable multi-processes and use the super-powerful processing mode of multi-processes and multi-coroutines. The simplest way is to directly set the number of process workers for the HTTP service.

$http->set(array(
    &#39;worker_num&#39; => 4,
      // &#39;worker_num&#39; => 1,单进程
));

Now run the server and you can see several more processes. Then we create a new test route

Route::get(&#39;/a&#39;, function () {
    echo Swoole\Coroutine::getCid(), "<br/>";
    print_r(Swoole\Coroutine::stats());
    echo "<br/>";
    echo getmypid(), "<br/>";
});

Now visit the homepage and this /a page again.

// 首页一
1
Array
(
    [event_num] => 2
    [signal_listener_num] => 0
    [aio_task_num] => 0
    [aio_worker_num] => 0
    [aio_queue_size] => 0
    [c_stack_size] => 2097152
    [coroutine_num] => 1
    [coroutine_peak_num] => 1
    [coroutine_last_cid] => 1
)
1562
// 首页二
1
Array
(
    [event_num] => 2
    [signal_listener_num] => 0
    [aio_task_num] => 0
    [aio_worker_num] => 0
    [aio_queue_size] => 0
    [c_stack_size] => 2097152
    [coroutine_num] => 1
    [coroutine_peak_num] => 1
    [coroutine_last_cid] => 1
)
1563
// /a 页面
1
Array
(
    [event_num] => 2
    [signal_listener_num] => 0
    [aio_task_num] => 0
    [aio_worker_num] => 0
    [aio_queue_size] => 0
    [c_stack_size] => 2097152
    [coroutine_num] => 1
    [coroutine_peak_num] => 1
    [coroutine_last_cid] => 1
)
1564

I found no, and their process IDs are all different. If there is no blocking, the process will be switched first. If all processes are blocked, the coroutine will be created in a loop for in-process processing.

The above is the detailed content of Try how to change Laravel to Swoole version. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete