协程能够理解为纯用户态的线程,其经过协做而不是抢占来进行切换,相对于进程或者线程,协程全部的操做均可以在用户态完成,建立和切换的消耗更低,Swoole 能够为每个请求建立对应的协程,根据 IO 的状态来合理的调度协程。php
在 Swoole 4.x 中,协程(Coroutine)取代了异步回调,成为 Swoole 官方推荐的编程方式。Swoole 协程解决了异步回调编程困难的问题,使用协程能够以传统同步编程的方法编写代码,底层自动切换为异步 IO,既保证了编程的简单性,又可借助异步 IO,提高系统的并发能力。html
开启swoole的http服务并设置提供给url访问页面的文件的根目录,nginx
代码以下。这样在浏览器只能访问…static下面的文件,而没法访问其余目录下的文件。laravel
http.serversql
<?php //开启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进程启动时发生。这里建立的对象能够在进程生命周期内使用。thinkphp
原型:shell
function onWorkerStart(swoole_server $server, int workerid);编程
(1)onWorkerStart/onStart是并发执行的,没有前后顺序;json
(2)能够经过server->taskworker属性来判断当前是Worker进程仍是Task进程;数组
(3)设置了worker_num和task_worker_num超过1时,每一个进程都会触发一次onWorkerStart事件,可经过判断$worker_id区分不一样的工做进程;
(4)由 worker 进程向 task 进程发送任务,task 进程处理彻底部任务以后经过onFinish回调函数通知worker 进程。
例如,咱们在后台操做向十万个用户群发通知邮件,操做完成后操做的状态显示为发送中,这时咱们能够继续其余操做。等邮件群发完毕后,操做的状态自动改成已发送。
在onWorkerStart中加载框架的核心文件后:
(1)不用每次请求都加载框架核心文件,提升性能;
(2)能够在后续的回调事件中继续使用框架的核心文件或者类库。
项目目录下的public文件夹下的index.php是入口文件,源码以下:
<?php // [ 应用入口文件 ] // 定义应用目录 define('APP_PATH', __DIR__ . '/../application/'); // 加载框架引导文件 require __DIR__ . '/../thinkphp/start.php';
这个文件加载了…thinkphp/start.php’,start.php加载了一个核心文件base.php,因此咱们须要把base.php文件加载到onWorkStart回调函数里面,每一个worker进程都会触发一次onWorkerStart事件,所以ThinkPHP框架内的入口文件等内容就能加载入咱们的项目。
修改http.server以下:
<?php //开启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页面。
能够打印出路由看看。在项目目录\thinkphp\library\think\App.php文件中的routeCheck接口,打印path变量,能够看到url改变后path变量并无改变。这是由于onWorkerStart进程加载框架的时候就复用了类成员变量。
/** * URL路由检测(根据PATH_INFO) * @access public * @return Dispatch */ public function routeCheck() { $path = $this->request->path(); echo "path:".$path."<br/>"; // 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')); }
修改:
进入 项目目录\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'], '/'); }
此时用浏览器访问:
好了各位,以上就是这篇文章的所有内容了,能看到这里的人呀,都是人才。以前说过,PHP方面的技术点不少,也是由于太多了,实在是写不过来,写过来了你们也不会看的太多,因此我这里把它整理成了PDF和文档,若是有须要的能够
更多学习内容能够访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)
以上内容但愿帮助到你们,不少PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提高,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货须要的能够免费分享给你们,须要的能够加入个人 PHP技术交流群