协程是什么?swoole完美支持TP5

2023-06-1911:23:51后端程序开发Comments1,443 views字数 4636阅读模式

协程是什么文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

协程可以理解为纯用户态的线程,其通过协作而不是抢占来进行切换,相对于进程或者线程,协程所有的操作都可以在用户态完成,创建和切换的消耗更低,Swoole 可以为每一个请求创建对应的协程,根据 IO 的状态来合理的调度协程。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

在 Swoole 4.x 中,协程(Coroutine)取代了异步回调,成为 Swoole 官方推荐的编程方式。Swoole 协程解决了异步回调编程困难的问题,使用协程可以以传统同步编程的方法编写代码,底层自动切换为异步 IO,既保证了编程的简单性,又可借助异步 IO,提升系统的并发能力。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

完美支持TP5,首先开启swoole的http服务文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

开启swoole的http服务并设置提供给url访问页面的文件的根目录,文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

代码如下。这样在浏览器只能访问…static下面的文件,而无法访问其他目录下的文件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

http.server文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html


//开启http server
$http = new swoole_http_server("0.0.0.0", 9905);
$http->set(
    [
        'enable_static_handler' => true,
        'document_root' => "/usr/local/openresty/nginx/html/swoole/LiveRadio/public/static",
        'worker_num' => 5
    ]
);
$http->on('request', function($request, $response) {
    $response->end("sss". json_encode($request->get));
});

$http->start();

swoole有一个事件回调函数onWorkStart,此事件在Worker进程/Task进程启动时发生。这里创建的对象可以在进程生命周期内使用。
原型:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

function onWorkerStart(swoole_server $server, int workerid);

(1)onWorkerStart/onStart是并发执行的,没有先后顺序;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

(2)可以通过server->taskworker属性来判断当前是Worker进程还是Task进程;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

(3)设置了worker_numtask_worker_num超过1时,每个进程都会触发一次onWorkerStart事件,可通过判断$worker_id区分不同的工作进程;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

(4)由 worker 进程向 task 进程发送任务,task 进程处理完全部任务之后通过onFinish回调函数通知worker 进程。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

例如,我们在后台操作向十万个用户群发通知邮件,操作完成后操作的状态显示为发送中,这时我们可以继续其他操作。等邮件群发完毕后,操作的状态自动改为已发送。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

onWorkerStart中加载框架的核心文件后:
(1)不用每次请求都加载框架核心文件,提高性能;
(2)可以在后续的回调事件中继续使用框架的核心文件或者类库。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

项目目录下的public文件夹下的index.php是入口文件,源码如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html


// [ 应用入口文件 ]
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

这个文件加载了…thinkphp/start.php’,start.php加载了一个核心文件base.php,所以我们需要把base.php文件加载到onWorkStart回调函数里面,每个worker进程都会触发一次onWorkerStart事件,因此ThinkPHP框架内的入口文件等内容就能加载入我们的项目。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

修改http.server如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html


//开启http server
$http = new swoole_http_server("0.0.0.0", 9906);
$http->set(
    [
        'enable_static_handler' => true,
        'document_root' => "/usr/local/openresty/nginx/html/swoole/LiveRadio/public/static",
        'worker_num' => 5  //设置worker进程数
    ]
);

$http->on('WorkerStart', function (swoole_server $server, $worker_id){
    //定义应用目录
    define('APP_PATH', __DIR__ . '/../application/');
    // 加载基础文件
    //这里不直接加载start.php的原因是start.php中的代码会直接执行,也就是application\index\controller\Index.php文件(框架的默认首页)
    /*
     * Container::get('app', [defined('APP_PATH') ? APP_PATH : ''])
    ->run()
    ->send();
    */
    require __DIR__ . '/../thinkphp/base.php';
});

$http->on('request', function($request, $response){
    //适配
    /*
     *由于swoole http提供的API和原生php代码是有所不同的,比如原生php中获取get参数为直接从全局数组_GET中获取,而swoole http中是通过$request->get()的方式获取,因此要转换成原生的
     * */

    $_SERVER = [];
    if(isset($request->server)){
        foreach($request->header as $k => $v){
            $_SERVER[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;
        }
    }

    //..其余参数用到的继续往后写

    ob_start();
    // 执行应用并响应
    try {
        think\Container::get('app', [APP_PATH])
            ->run()
            ->send();
    }catch (\Exception $e){
        //todo
    }
    $res = ob_get_contents();
    ob_end_clean();
    $response->end($res);
});

$http->start();

此时,用浏览器访问 http://ip:port/?s=index/index/index 可以看到ThinkPHP的默认首页,但是发现访问不到http://ip:port/?s=index/index/hello?name=world页面。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

可以打印出路由看看。在项目目录\thinkphp\library\think\App.php文件中的routeCheck接口,打印path变量,可以看到url改变后path变量并没有改变。这是因为onWorkerStart进程加载框架的时候就复用了类成员变量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

    /**
     * URL路由检测(根据PATH_INFO)
     * @access public
     * @return Dispatch
     */
    public function routeCheck()
    {
        $path = $this->request->path();
        echo "path:".$path."
";
//        var_dump($this->request);
        $depr = $this->config('app.pathinfo_depr');

        // 路由检测
        $files = scandir($this->routePath);
        foreach ($files as $file) {
            if (strpos($file, '.php')) {
                $filename = $this->routePath . DIRECTORY_SEPARATOR . $file;
                // 导入路由配置
                $rules = include $filename;
                if (is_array($rules)) {
                    $this->route->import($rules);
                }
            }
        }

        // 是否强制路由模式
        $must = !is_null($this->routeMust) ? $this->routeMust : $this->config('app.url_route_must');

        // 路由检测 返回一个Dispatch对象
        return $this->route->check($path, $depr, $must, $this->config('app.route_complete_match'));
    }

修改:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

进入 项目目录\thinkphp\library\think\Request.php中文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

(1)找到function path() { },注销判断,不再复用类成员变量 $ this->path。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

(2)找到function pathinfo() { },注销判断,不再复用类成员变量$this->pathinfo。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

(3)使其支持pathinfo路由,在function pathinfo() { }中添加代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != '/') {
    return ltrim($_SERVER['PATH_INFO'], '/');
}
协程是什么?swoole完美支持TP5

此时用浏览器访问:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html

协程是什么?swoole完美支持TP5
协程是什么?swoole完美支持TP5
文章源自菜鸟学院-https://www.cainiaoxueyuan.com/bc/47423.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/bc/47423.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定