Swoole在Tp5.1中的使用

1.1 面向过程方案

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

$http->set([
    'worker_num' => 5,
]);
$http->on('WorkerStart', function(swoole_server $server,  $worker_id) {
    // 定义应用目录
    define('APP_PATH', __DIR__ . '/../../application/');
    // 加载框架里面的文件
    require __DIR__ . '/../base.php';
    //require __DIR__ . '/../thinkphp/start.php';
});
$http->on('request', function($request, $response) use($http){

    $_SERVER  =  [];
    if(isset($request->server)) {
        foreach($request->server as $k => $v) {
            $_SERVER[strtoupper($k)] = $v;
        }
    }
    if(isset($request->header)) {
        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();
    // 执行应用并响应
    think\Container::get('app', [APP_PATH])->run()->send();
    // echo "-action-".request()->action().PHP_EOL;
    $res = ob_get_contents();
    ob_end_clean();
    $response->end($res);
    // $http->close($http->fd);
});

$http->start();

    onWorkerStart:

    此事件在Worker进程/Task进程启动时发生,这里创建的对象可以在进程生命周期内使用
    在onWorkerStart中加载框架的核心文件后:

  1. 不用每次请求都加载框架核心文件,提高性能
  2. 可以在后续的回调事件中继续使用框架的核心文件或者类库

结果展示:(监听9501端口,路由需要配置,暂时用s=url 的方式.)


thinkphp5.1核心版本源码修改

修改 ThinkPHP5框架 Request.php源码位置: /thinkphp/library/think/Request.php

    修改如下:

  1. function path() { }
    //注销判断,不再复用类成员变量$this->path
  2. function pathinfo() { }
    //注销判断,不再复用类成员变量$this->pathinfo
  3. 使其支持pathinfo路由,添加如下代码在function pathinfo() { }
if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != '/') {
       return ltrim($_SERVER['PATH_INFO'], '/');
 }
完整的 Request.php
    /**
     * 获取当前请求URL的pathinfo信息(含URL后缀)
     * @access public
     * @return string
     */
    public function pathinfo()
    {
        if (isset($_SERVER['PATH_INFO']) && $_SERVER['PATH_INFO'] != '/') {
            return ltrim($_SERVER['PATH_INFO'], '/');
        }
//        if (is_null($this->pathinfo)) {
            if (isset($_GET[$this->config->get('var_pathinfo')])) {
                // 判断URL里面是否有兼容模式参数
                $_SERVER['PATH_INFO'] = $_GET[$this->config->get('var_pathinfo')];
                unset($_GET[$this->config->get('var_pathinfo')]);
            } elseif ($this->isCli()) {
                // CLI模式下 index.php module/controller/action/params/...
                $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
            }

            // 分析PATHINFO信息
            if (!isset($_SERVER['PATH_INFO'])) {
                foreach ($this->config->get('pathinfo_fetch') as $type) {
                    if (!empty($_SERVER[$type])) {
                        $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
                        substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
                        break;
                    }
                }
            }

            $this->pathinfo = empty($_SERVER['PATH_INFO']) ? '/' : ltrim($_SERVER['PATH_INFO'], '/');
//        }

        return $this->pathinfo;
    }

    /**
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
     * @access public
     * @return string
     */
    public function path()
    {
    //注销判断,不再复用类成员变量$this->path
//        if (is_null($this->path)) {
            $suffix   = $this->config->get('url_html_suffix');
            $pathinfo = $this->pathinfo();
            if (false === $suffix) {
                // 禁止伪静态访问
                $this->path = $pathinfo;
            } elseif ($suffix) {
                // 去除正常的URL后缀
                $this->path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
            } else {
                // 允许任何后缀访问
                $this->path = preg_replace('/\.' . $this->ext() . '$/i', '', $pathinfo);
            }
//        }

        return $this->path;
    }

1.2面向对象方案

class Http {
    CONST HOST = "0.0.0.0";
    CONST PORT = 9911;

    public $http = null;
    public function __construct() {
        $this->http = new swoole_http_server(self::HOST, self::PORT);

        $this->http->set(
            [
                'enable_static_handler' => true,
                'document_root' => "/home/wwwroot/swoole/thinkphp/public/static",
                'worker_num' => 4,
            ]
        );

        $this->http->on("workerstart", [$this, 'onWorkerStart']);
        $this->http->on("request", [$this, 'onRequest']);
        $this->http->on("close", [$this, 'onClose']);

        $this->http->start();
    }

    /**
     * 此事件在Worker进程/Task进程启动时发生,这里创建的对象可以在进程生命周期内使用
     * 在onWorkerStart中加载框架的核心文件后
     * 1.不用每次请求都加载框架核心文件,提高性能
     * 2.可以在后续的回调中继续使用框架的核心文件或者类库
     *
     * @param $server
     * @param $worker_id
     */
    public function onWorkerStart($server,  $worker_id) {
        // 定义应用目录
        define('APP_PATH', __DIR__ . '/../../../../application/');
        // 加载框架里面的文件
        require __DIR__ . '/../../../../thinkphp/base.php';
    }

    /**
     * request回调
     * 解决上一次输入的变量还存在的问题例:$_SERVER  =  []
     * @param $request
     * @param $response
     */
    public function onRequest($request, $response) {
        $_SERVER  =  [];
        if(isset($request->server)) {
            foreach($request->server as $k => $v) {
                $_SERVER[strtoupper($k)] = $v;
            }
        }
        if(isset($request->header)) {
            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;
            }
        }
        $_POST['http_server'] = $this->http;

        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);
    }
    /**
     * close
     * @param $ws
     * @param $fd
     */
    public function onClose($ws, $fd) {
        echo "clientid:{$fd}\n";
    }
}
new Http();

1.3分发Task异步任务机制实现

<?php

/**
*	 socket面向对象的编译
*/
class Ws
{
	CONST HOST='0.0.0.0';
	CONST PORT='9501';
	public $ws=null;

	public function __construct()
	{
		$this->ws=new swoole_http_server(self::HOST,self::PORT);
		$this->ws->set([
			//启动task必须要设置其数量
			'worker_num' => 4,
            'task_worker_num' => 4,
		]);
		$this->ws->on('workerStart',[$this,'onWorkerStart']);
		$this->ws->on('request',[$this,'onRequest']);
		$this->ws->on('task',[$this,'onTask']);
		$this->ws->on('finish',[$this,'onFinish']);
		$this->ws->on('close',[$this,'onclose']);
		$this->ws->start();
	}

	/**
		监听开启事件的回调
	*/
	public function onWorkerStart($server, $worker_id)
	{
		// 定义应用目录
	    define('APP_PATH', __DIR__ . '/../application/');
	    // 加载框架里面的文件
	    require __DIR__ . '/../thinkphp/base.php';
	}
	
 	/**
     * request回调
     * @param $request
     * @param $response
     */
    public function onRequest($request, $response) {
        $_SERVER  =  [];
        if(isset($request->server)) {
            foreach($request->server as $k => $v) {
                $_SERVER[strtoupper($k)] = $v;
            }
        }
        if(isset($request->header)) {
            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;
            }
        }
        $_POST['http_server'] = $this->ws;

        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);
    }
	/**
		监听关闭事件的回调
	*/
	public function onclose($ser, $fd)
	{
		print_r("你好,我的{$fd}\n");
	}

	/**
	*	$serv 			服务
	*	$task_id		任务ID,由swoole扩展内自动生成,用于区分不同的任务
	*	$src_worker_id 	$task_id和$src_worker_id组合起来才是全局唯一的,不同的worker进程投递的任务ID可能会有相同
	*	$data 			是任务的内容
	*/
	 public function onTask($serv,$task_id,$src_worker_id,$data)
	{
		//在终端输出
		print_r($data).'/n';
		//执行耗时任务
		sleep(10);
		//回调于onFinish
		return '你成了-A';
	}
	/**
	*	$task_id 		是任务的ID
	*	$data			是任务处理的结果内容
	*/
	 public function onFinish($serv,$task_id,$data)
	{
		print_r($data).'/n';
	}

}

new Ws();

控制器中,千万不要再系统默认加载的控制器下写task,否则你就会发现多执行了一次任务,切记!切记!切记!

控制器:
<?php
namespace app\index\controller;

class Index
{
    public function index()
    {
    	$data='我是分发任务';
        $a=$_POST['http_server']->task($data);
        echo $a.PHP_EOL;
        return 123;
    }

    public function a()
    {
        $data='我是分发任务aaaaaa';
        $a=$_POST['http_server']->task($data);
        return 123456798;
    }
    public function bbb()
    {
        return 1111111111111111;
    }
}

结果展示:

执行控制器a,结果发现多执行了一次,就是那个坑!!!





猜你喜欢

转载自blog.csdn.net/feiwutudou/article/details/80180179
今日推荐