Use swoole in ThinkPHP5

Posted by bernard_hinault on Tue, 10 Dec 2019 09:51:17 +0100

(Note: This is just the beginning of the combination of swoole and TP5. I think there will be more holes to step on when they are deeply integrated! )
 
First go TP official website Download framework
 

General overview:
 

Create a new server folder in the root directory of the project,
The content of http_server.php is as follows (it can be directly copied for use in the past):

<?php
/**
 * Created by PhpStorm.
 * User: baidu
 * Date: 18/2/28
 * Time: 1:39 a.m.
 */
$http = new swoole_http_server("0.0.0.0", 8811);

$http->set(
    [
        'enable_static_handler' => true,
        'document_root' => "/home/work/swoole/thinkphpcore/public",
        'worker_num'    => 5,
        'content-type' => 'text/html; charset=utf-8',
    ]
);
$http->on('WorkerStart', function (swoole_server $server, $worker_id) {
    // Define application directory
    define('APP_PATH', __DIR__ . '/../application/');
    // 1. Load basic file
    require __DIR__ . '/../thinkphpcore/base.php';
    // You can't load the frame content in this way. You can open it if you don't believe it
    // require __DIR__ . '/../thinkphpcore/start.php';
});
$http->on('request', function($request, $response) use ($http) {
    //print_r($request->get);
    $content = [
        'date:' => date("Ymd H:i:s"),
        'get:' => $request->get,
        'post:' => $request->post,
        'header:' => $request->header,
    ];

    swoole_async_writefile(__DIR__."/access.log", json_encode($content).PHP_EOL, function($filename) {
        // todo
    }, FILE_APPEND);

    $_SERVER = [];
    if (isset($request->server)) {
        foreach ($request->server as $k => $v) {
            $_SERVER[strtoupper($k)] = $v;
        }
    }

    $_HEADER = [];
    if (isset($request->header)) {
        foreach ($request->header as $k => $v) {
            $_HEADER[strtoupper($k)] = $v;
        }
    }

    $_GET = [];
    if (isset($request->get)) {
        foreach ($request->get as $k => $v) {
            $_GET[$k] = $v;
        }
    }

    $_POST = [];
    if (isset($request->post)) {
        foreach ($request->post as $k => $v) {
            $_POST[$k] = $v;
        }
    }

    // 2. Execute application
    ob_start();
    try {
        think\App::run()->send();
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    $res = ob_get_contents();
    ob_end_clean();
    $response->end($res);
    // This is a simple and crude way to destroy processes and reload framework content
    // $http->close($request);
});

$http->start();

I: open URL normal mode
Find the pathinfo() and path() methods of thinkphp5 thinkpcore library think request.php
Comment out the if (is? Null) statements in these two places
Because if the variable pathinfo is not annotated, it will only store the value saved by the first run of the framework

/**
     * Get pathinfo information of current request URL (including URL suffix)
     * @access public
     * @return string
     */
    public function pathinfo()
    {
//        if (is_null($this->pathinfo)) {
            ...
                        ...
                        ...
//        }
        return $this->pathinfo;
    }

    /**
     * Get pathinfo information of current request URL (excluding URL suffix)
     * @access public
     * @return string
     */
    public function path()
    {
//        if (is_null($this->path)) {
           ...
                     ...
                     ...
//        }
        return $this->path;
    }

The effect visit is as follows:

2. Enable pathinfo mode:

/**
     * Get pathinfo information of current request URL (including URL suffix)
     * @access public
     * @return string
     */
    public function pathinfo()
    {
                    // Configure pathinfo 
                    if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != '/') {
                            return ltrim($_SERVER['PATH_INFO'], '/');
                    }
                    // Configure normal access mode
//        if (is_null($this->pathinfo)) {
            ...
                        ...
                        ...
//        }
        return $this->pathinfo;
    }

    /**
     * Get pathinfo information of current request URL (excluding URL suffix)
     * @access public
     * @return string
     */
    public function path()
    {
//        if (is_null($this->path)) {
           ...
                     ...
                     ...
//        }
        return $this->path;
    }

The interview effect is as follows:

Index.php example code:

<?php

namespace app\index\controller;

use think\request;

class Index
{
    public function index(Request $request)
    {
        return 'hello-swoole';
    }

    public function check()
    {
        print_r($_GET);
        return time();
    }

    public function getClientIp()
    {
        $list = swoole_get_local_ip();
        print_r($list);
    }
}

 
Official introduction of Swoole: HttpServer

  • The support of swoole? Http? Server for Http protocol is not complete, so it is recommended to only be an application server. And add Nginx as the agent in the front end
  • swoole-1.7.7 adds the support of built-in Http server. An asynchronous non blocking multiprocess Http server can be written in a few lines of code.

    $http = new swoole_http_server("127.0.0.1", 9501);
    $http->on('request', function ($request, $response) {
    $response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
    });
    $http->start();

Through the use of apache bench tool for stress testing, on the common PC machine with inter core-i54 core + 8G memory, the swoole ﹣ http ﹣ server can reach nearly 110000 QPS. Far more than PHP FPM, golang has its own HTTP server, and node.js has its own HTTP server. The performance is close to the static file processing of Nginx.

ab -c 200 -n 200000 -k http://127.0.0.1:9501

Topics: PHP Nginx PhpStorm Apache