摘要:引导程序包括完成环境检测配置加载异常处理注册服务提供者注册启动服务这六个引导程序。处理请求请求处理发生在内核的方法内。发送响应头部信息发送报文主题终止程序程序终止,完成终止中间件的调用终止中间件以上便是的请求生命周期的始末。
本文首发于个人博客 深度挖掘 Laravel 生命周期,转载请注明出处。
这篇文章我们来聊聊 「Laravel 生命周期」 这个主题。虽然网络上已经有很多关于这个主题的探讨,但这个主题依然值得我们去研究和学习。
我想说的是当我们在决定使用某项技术的时候,除了需要了解它能「做什么」,其实还应当研究它是「怎么做的」。
Laravel 框架或者说任何一个 Web 项目,我们都需要理解它究竟是如何接收到用户发起的 HTTP 请求的;又是如何响应结果给用户的;在处理请求和响应的过程中都存在哪些处理值得深入学习。
所有这些内容其实都包含在 「Laravel 生命周期」 这个主题里面。
本文较长建议使用合适的 IDE 进行代码查阅;或者通过文中的链接,或是代码注释的 「@see」部分直接在 Github 畅读代码。
目录结构一 摘要
二 生命周期之始末
2.1 加载项目依赖
2.2 创建 Laravel 应用实例
2.2.1 创建应用实例
2.2.2 内核绑定
2.2.3 注册异常处理
2.2.4 小结
2.3 接收请求并响应
2.3.1 解析内核实例
2.3.2 处理 HTTP 请求
2.3.2.1 创建请求实例
2.3.2.2 处理请求
2.3.2.2.1 启动「引导程序」
2.3.2.2.2 发送请求至路由
2.4 发送响应
2.5 终止程序
三 总结
四 生命周期流程图
参考资料
一 摘要Laravel 生命周期(或者说请求生命周期)概括起来主要分为 3 个主要阶段:
加载项目依赖
创建 Laravel 应用实例
接收请求并响应
而这 3 个阶段的处理都发生在入口文件 public/index.php 文件内(public/index.php 是一个新安装的 Laravel 项目默认入口文件)。
然而 index.php 文件仅包含极少的代码,但却出色的完成了一个 HTTP 请求从接收到响应的全部过程,逻辑组织的几近完美。
我们来看下入口文件实现的代码:
make(IlluminateContractsHttpKernel::class); $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); $response->send(); // 其它 $kernel->terminate($request, $response);二 生命周期之始末 2.1 加载项目依赖
现代 PHP 依赖于 Composer 包管理器,入口文件通过引入由 Composer 包管理器自动生成的类加载程序,可以轻松注册并加载项目所依赖的第三方组件库。
所有组件的加载工作,仅需一行代码即可完成:
require __DIR__."/../vendor/autoload.php";2.2 创建 Laravel 应用实例
创建应用实例(或称服务容器),由位于 bootstrap/app.php 文件里的引导程序完成,创建服务容器的过程即为应用初始化的过程,项目初始化时将完成包括:注册项目基础服务、注册项目服务提供者别名、注册目录路径等在内的一些列注册工作。
下面是 bootstrap/app.php 的代码,包含两个主要部分「创建应用实例」和「绑定内核至 APP 服务容器」:
singleton( IlluminateContractsHttpKernel::class, AppHttpKernel::class ); $app->singleton( IlluminateContractsConsoleKernel::class, AppConsoleKernel::class ); $app->singleton( IlluminateContractsDebugExceptionHandler::class, AppExceptionsHandler::class ); return $app;2.2.1 创建应用实例
创建应用实例即实例化 IlluminateFoundationApplication 这个服务容器,后续我们称其为 APP 容器。在创建 APP 容器主要会完成:注册应用的基础路径并将路径绑定到 APP 容器 、注册基础服务提供者至 APP 容器 、注册核心容器别名至 APP 容器 等基础服务的注册工作。
/** * Create a new Illuminate application instance. * * @see https://github.com/laravel/framework/blob/5.6/src/Illuminate/Foundation/Application.php#L162:27 * @param string|null $basePath * @return void */ public function __construct($basePath = null) { if ($basePath) { $this->setBasePath($basePath); } $this->registerBaseBindings(); $this->registerBaseServiceProviders(); $this->registerCoreContainerAliases(); }2.2.2 内核绑定
接着将关注的焦点转移到绑定内核部分。
Laravel 会依据 HTTP 请求的运行环境的不同,将请求发送至相应的内核: HTTP 内核 或 Console 内核。无论 HTTP 内核还是 Console 内核,它们的作用都是是接收一个 HTTP 请求,随后返回一个响应,就是这么简单。
这篇文章主要研究 HTTP 内核,HTTP 内核继承自 IlluminateFoundationHttpKernel 类.
在 「HTTP 内核」 内它定义了 中间件 相关数组;在 「IlluminateFoundationHttpKernel」 类内部定义了属性名为 「bootstrappers」 的 引导程序 数组。
中间件 提供了一种方便的机制来过滤进入应用的 HTTP 请求。
「引导程序」 包括完成环境检测、配置加载、异常处理、Facades 注册、服务提供者注册、启动服务这六个引导程序。
至于 「中间件」 和 「引导程序」如何被使用的,会在后面的章节讲解。
2.2.3 注册异常处理项目的异常处理由 AppExceptionsHandler::class 类完成,这边也不做深入的讲解。
2.2.4 本节小结通过上面的分析我们可以发现在「创建 Laravel 应用实例」这个阶段它做了很多的基础工作,包括但不限于:创建 APP 容器、注册应用路径、注册基础服务提供者、配置中间件和引导程序等。
2.3 接收请求并响应在完成创建 APP 容器后即进入了第三个阶段 「接收请求并响应」。
「接收请求并响应」有关代码如下:
$kernel = $app->make(IlluminateContractsHttpKernel::class); $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); $response->send();
我们需要逐行分析上面的代码,才能窥探其中的原貌。
2.3.1 解析内核实例在第二阶段我们已经将 HTTP 内核 和 Console 内核 绑定到了 APP 容器,使用时通过 APP 容器 的 make() 方法将内核解析出来,解析的过程就是内核实例化的过程。
$kernel = $app->make(IlluminateContractsHttpKernel::class);
内核实例化时它的内部究竟又做了哪些操作呢?
进一步挖掘 IlluminateFoundationHttpKernel 内核的 __construct(IlluminateContractsFoundationApplication $app, IlluminateRoutingRouter $router) 构造方法,它接收 APP 容器 和 路由器 两个参数。
在实例化内核时,构造函数内将在 HTTP 内核定义的「中间件组」注册到 路由器,注册完后就可以在实际处理 HTTP 请求前调用这些「中间件」实现 过滤 请求的目的。
... /** * Create a new HTTP kernel instance. 创建 HTTP 内核实例 * * @class IlluminateFoundationHttpKernel * @param IlluminateContractsFoundationApplication $app * @param IlluminateRoutingRouter $router * @return void */ public function __construct(Application $app, Router $router) { $this->app = $app; $this->router = $router; $router->middlewarePriority = $this->middlewarePriority; foreach ($this->middlewareGroups as $key => $middleware) { $router->middlewareGroup($key, $middleware); } foreach ($this->routeMiddleware as $key => $middleware) { $router->aliasMiddleware($key, $middleware); } } ...
... /** * Register a group of middleware. 注册中间件组 * * @class IlluminateRoutingRouter * @param string $name * @param array $middleware * @return $this */ public function middlewareGroup($name, array $middleware) { $this->middlewareGroups[$name] = $middleware; return $this; } /** * Register a short-hand name for a middleware. 注册中间件别名 * * @class IlluminateRoutingRouter * @param string $name * @param string $class * @return $this */ public function aliasMiddleware($name, $class) { $this->middleware[$name] = $class; return $this; } ...2.3.2 处理 HTTP 请求
之前的所有处理,基本都是围绕在配置变量、注册服务等运行环境的构建上,构建完成后才是真刀真枪的来处理一个「HTTP 请求」。
处理请求实际包含两个阶段:
创建请求实例
处理请求
// 处理请求 $response = $kernel->handle( // 创建请求实例 $request = IlluminateHttpRequest::capture() );
请求实例 IlluminateHttpRequest 的 capture() 方法内部通过 Symfony 实例创建一个 Laravel 请求实例。这样我们就可以获取到用户请求报文的相关信息了。
/** * Create a new Illuminate HTTP request from server variables. * * @class IlluminateHttpRequest * @return static */ public static function capture() { static::enableHttpMethodParameterOverride(); return static::createFromBase(SymfonyRequest::createFromGlobals()); } /** * Create an Illuminate request from a Symfony instance. * * @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php * @param SymfonyComponentHttpFoundationRequest $request * @return IlluminateHttpRequest */ public static function createFromBase(SymfonyRequest $request) { if ($request instanceof static) { return $request; } $content = $request->content; $request = (new static)->duplicate( $request->query->all(), $request->request->all(), $request->attributes->all(), $request->cookies->all(), $request->files->all(), $request->server->all() ); $request->content = $content; $request->request = $request->getInputSource(); return $request; }
请求处理发生在 HTTP 内核 的 handle() 方法内。
/** * Handle an incoming HTTP request. * * @class IlluminateFoundationHttpKernel * @param IlluminateHttpRequest $request * @return IlluminateHttpResponse */ public function handle($request) { try { $request->enableHttpMethodParameterOverride(); $response = $this->sendRequestThroughRouter($request); } catch (Exception $e) { $this->reportException($e); $response = $this->renderException($request, $e); } catch (Throwable $e) { $this->reportException($e = new FatalThrowableError($e)); $response = $this->renderException($request, $e); } $this->app["events"]->dispatch( new EventsRequestHandled($request, $response) ); return $response; }
handle() 方法接收一个 HTTP 请求,并最终生成一个 HTTP 响应。
继续深入到处理 HTTP 请求的方法 $this->sendRequestThroughRouter($request) 内部。
/** * Send the given request through the middleware / router. * * @see https://github.com/laravel/framework/blob/5.6/src/Illuminate/Foundation/Http/Kernel.php * @param IlluminateHttpRequest $request * @return IlluminateHttpResponse */ protected function sendRequestThroughRouter($request) { $this->app->instance("request", $request); Facade::clearResolvedInstance("request"); $this->bootstrap(); return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }
将发现这段代码没有一行废话,它完成了大量的逻辑处理:
首先,将 $request 实例注册到 APP 容器 供后续使用;
之后,清除之前 $request 实例缓存;
然后,启动「引导程序」;
最后,发送请求至路由。
记得我们在之前「2.2.2 内核绑定」章节,有介绍在「HTTP 内核」中有把「引导程序(bootstrappers)」绑定到了 APP 容器,以及这些引导程序的具体功能。
但是没有聊如何调用这些「引导程序」。
/** * Send the given request through the middleware / router. * * @see https://github.com/laravel/framework/blob/5.6/src/Illuminate/Foundation/Http/Kernel.php * @param IlluminateHttpRequest $request * @return IlluminateHttpResponse */ protected function sendRequestThroughRouter($request) { ... // 启动 「引导程序」 $this->bootstrap(); ... }
上面的代码块说明在 $this->bootstrap(); 方法内部有实际调用「引导程序」,而 bootstrap() 实际调用的是 APP 容器的 bootstrapWith(),来看看
... /** * The bootstrap classes for the application. 应用的引导程序 * * @var array */ protected $bootstrappers = [ IlluminateFoundationBootstrapLoadEnvironmentVariables::class, IlluminateFoundationBootstrapLoadConfiguration::class, IlluminateFoundationBootstrapHandleExceptions::class, IlluminateFoundationBootstrapRegisterFacades::class, IlluminateFoundationBootstrapRegisterProviders::class, IlluminateFoundationBootstrapBootProviders::class, ]; /** * Bootstrap the application for HTTP requests. * * @class IlluminateFoundationHttpKernel * @return void */ public function bootstrap() { if (! $this->app->hasBeenBootstrapped()) { $this->app->bootstrapWith($this->bootstrappers()); } } protected function bootstrappers() { return $this->bootstrappers; } ...
最终还是要看 IlluminateFoundationApplication 的 bootstrapWith() 方法究竟如何来启动这些引导程序的。
/** * Run the given array of bootstrap classes. * * @class IlluminateFoundationApplication APP 容器 * @param array $bootstrappers * @return void */ public function bootstrapWith(array $bootstrappers) { $this->hasBeenBootstrapped = true; foreach ($bootstrappers as $bootstrapper) { $this["events"]->fire("bootstrapping: ".$bootstrapper, [$this]); $this->make($bootstrapper)->bootstrap($this); $this["events"]->fire("bootstrapped: ".$bootstrapper, [$this]); } }
我们看到在 APP 容器内,会先解析对应的「引导程序」(即实例化),随后调用「引导程序」的 bootstrap() 完成的「引导程序」的启动操作。
作为示例我们随便挑一个「引导程序」来看看其内部的启动原理。
这边我们选 IlluminateFoundationBootstrapLoadConfiguration::class,它的功能是加载配置文件。
还记得我们讲解「2.2 创建 Laravel 应用实例」章节的时候有「注册应用的基础路径并将路径绑定到 APP 容器」。此时,LoadConfiguration 类就是将 config 目录下的所有配置文件读取到一个集合中,这样我们就可以项目里通过 config() 辅助函数获取配置数据。
getCachedConfigPath())) { $items = require $cached; $loadedFromCache = true; } $app->instance("config", $config = new Repository($items)); if (! isset($loadedFromCache)) { $this->loadConfigurationFiles($app, $config); } $app->detectEnvironment(function () use ($config) { return $config->get("app.env", "production"); }); date_default_timezone_set($config->get("app.timezone", "UTC")); mb_internal_encoding("UTF-8"); } /** * Load the configuration items from all of the files. * * @param IlluminateContractsFoundationApplication $app * @param IlluminateContractsConfigRepository $repository * @return void * @throws Exception */ protected function loadConfigurationFiles(Application $app, RepositoryContract $repository) { $files = $this->getConfigurationFiles($app); if (! isset($files["app"])) { throw new Exception("Unable to load the "app" configuration file."); } foreach ($files as $key => $path) { $repository->set($key, require $path); } } ... }
所有 「引导程序」列表功能如下:
IlluminateFoundationBootstrapLoadEnvironmentVariables : 环境检测,通过 DOTENV 组件将 .env 配置文件载入到 $_ENV 变量中;
IlluminateFoundationBootstrapLoadConfiguration : 加载配置文件,这个我们刚刚分析过;
IlluminateFoundationBootstrapHandleExceptions : 异常处理;
IlluminateFoundationBootstrapRegisterFacades : 注册 Facades,注册完成后可以以别名的方式访问具体的类;
IlluminateFoundationBootstrapRegisterProviders : 注册服务提供者,我们在 「2.2.1 创建应用实例」已经将基础服务提供者注册到 APP 容器。在这里我们会将配置在 app.php 文件夹下 providers 节点的服务器提供者注册到 APP 容器,供请求处理阶段使用;
IlluminateFoundationBootstrapBootProviders : 启动服务
完成「引导程序」启动操作后,随机进入到请求处理阶段。
/** * Send the given request through the middleware / router. * * @see https://github.com/laravel/framework/blob/5.6/src/Illuminate/Foundation/Http/Kernel.php * @param IlluminateHttpRequest $request * @return IlluminateHttpResponse */ protected function sendRequestThroughRouter($request) { ... // 发送请求至路由 return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter()); }
在 「发送请求至路由」这行代码中,完成了:管道(pipeline)创建、将 $request 传入管道、对 $request 执行「中间件」处理和实际的请求处理四个不同的操作。
在开始前我们需要知道在 Laravel 中有个「中间件」 的概念,即使你还不知道,也没关系,仅需知道它的功能是在处理请求操作之前,对请求进行过滤处理即可,仅当请求符合「中间件」的验证规则时才会继续执行后续处理。
有关 「管道」的相关知识不在本文讲解范围内。
那么,究竟一个请求是如何被处理的呢?
我们来看看 $this->dispatchToRouter() 这句代码,它的方法声明如下:
/** * Get the route dispatcher callback. 获取一个路由分发器匿名函数 * * @see https://github.com/laravel/framework/blob/5.6/src/Illuminate/Foundation/Http/Kernel.php * @return Closure */ protected function dispatchToRouter() { return function ($request) { $this->app->instance("request", $request); return $this->router->dispatch($request); }; }
回顾下「2.3.1 解析内核实例」章节,可知我们已经将 IlluminateRoutingRouter 对象赋值给 $this->router 属性。
通过 router 实例的 disptach() 方法去执行 HTTP 请求,在它的内部会完成如下处理:
查找对应的路由实例
通过一个实例栈运行给定的路由
运行在 routes/web.php 配置的匹配到的控制器或匿名函数
返回响应结果
currentRequest = $request; return $this->dispatchToRoute($request); } /** * Dispatch the request to a route and return the response. * * @param IlluminateHttpRequest $request * @return mixed */ public function dispatchToRoute(Request $request) { return $this->runRoute($request, $this->findRoute($request)); } /** * Find the route matching a given request. 1. 查找对应的路由实例 * * @param IlluminateHttpRequest $request * @return IlluminateRoutingRoute */ protected function findRoute($request) { $this->current = $route = $this->routes->match($request); $this->container->instance(Route::class, $route); return $route; } /** * Return the response for the given route. 2. 通过一个实例栈运行给定的路由 * * @param Route $route * @param Request $request * @return mixed */ protected function runRoute(Request $request, Route $route) { $request->setRouteResolver(function () use ($route) { return $route; }); $this->events->dispatch(new EventsRouteMatched($route, $request)); return $this->prepareResponse($request, $this->runRouteWithinStack($route, $request) ); } /** * Run the given route within a Stack "onion" instance. 通过一个实例栈运行给定的路由 * * @param IlluminateRoutingRoute $route * @param IlluminateHttpRequest $request * @return mixed */ protected function runRouteWithinStack(Route $route, Request $request) { $shouldSkipMiddleware = $this->container->bound("middleware.disable") && $this->container->make("middleware.disable") === true; $middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route); // 4. 返回响应结果 return (new Pipeline($this->container)) ->send($request) ->through($middleware) ->then(function ($request) use ($route) { return $this->prepareResponse( // 3. 运行在 routes/web.php 配置的匹配到的控制器或匿名函数 $request, $route->run() ); }); }
执行 $route->run() 的方法定义在 IlluminateRoutingRoute 类中,最终执行「在 routes/web.php 配置的匹配到的控制器或匿名函数」:
/** * Run the route action and return the response. * * @see https://github.com/laravel/framework/blob/5.6/src/Illuminate/Routing/Route.php * @return mixed */ public function run() { $this->container = $this->container ?: new Container; try { if ($this->isControllerAction()) { return $this->runController(); } return $this->runCallable(); } catch (HttpResponseException $e) { return $e->getResponse(); } }
这部分如果路由的实现是一个控制器,会完成控制器实例化并执行指定方法;如果是一个匿名函数则直接调用这个匿名函数。
其执行结果会通过 IlluminateRoutingRouter::prepareResponse($request, $response) 生一个响应实例并返回。
至此,Laravel 就完成了一个 HTTP 请求的请求处理。
2.4 发送响应经过一系列漫长的操作,HTTP 请求进入的最终章 - 发送响应值客户端 $response->send()。
make(IlluminateContractsHttpKernel::class); $response = $kernel->handle( $request = IlluminateHttpRequest::capture() ); // 发送响应 $response->send(); // 其它 $kernel->terminate($request, $response);
发送响应由 IlluminateHttpResponse 父类 SymfonyComponentHttpFoundationResponse 中的 send() 方法完成。
/** * Sends HTTP headers and content. * * @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Response.php * @return $this */ public function send() { $this->sendHeaders();// 发送响应头部信息 $this->sendContent();// 发送报文主题 if (function_exists("fastcgi_finish_request")) { fastcgi_finish_request(); } elseif (!in_array(PHP_SAPI, array("cli", "phpdbg"), true)) { static::closeOutputBuffers(0, true); } return $this; }2.5 终止程序
程序终止,完成终止中间件的调用
// @see https://github.com/laravel/framework/blob/5.6/src/Illuminate/Foundation/Http/Kernel.php public function terminate($request, $response) { $this->terminateMiddleware($request, $response); $this->app->terminate(); } // 终止中间件 protected function terminateMiddleware($request, $response) { $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge( $this->gatherRouteMiddleware($request), $this->middleware ); foreach ($middlewares as $middleware) { if (! is_string($middleware)) { continue; } list($name, $parameters) = $this->parseMiddleware($middleware); $instance = $this->app->make($name); if (method_exists($instance, "terminate")) { $instance->terminate($request, $response); } } }
以上便是 Laravel 的请求生命周期的始末。
三 总结在 「创建 Laravel 应用实例」时不仅会注册项目基础服务、注册项目服务提供者别名、注册目录路径等在内的一系列注册工作;还会绑定 HTTP 内核及 Console 内核到 APP 容器, 同时在 HTTP 内核里配置中间件和引导程序。
进入 「接收请求并响应」里,会依据运行环境从 APP 容器 解析出 HTTP 内核或 Console 内核。如果是 HTTP 内核,还将把「中间件」及「引导程序」注册到 APP 容器。
所有初始化工作完成后便进入「处理 HTTP 请求」阶段。
一个 Http 请求实例会被注册到 APP 容器,通过启动「引导程序」来设置环境变量、加载配置文件等等系统环境配置;
随后请求被分发到匹配的路由,在路由中执行「中间件」以过滤不满足校验规则的请求,只有通过「中间件」处理的请求才最终处理实际的控制器或匿名函数生成响应结果。
最后发送响应给用户,清理项目中的中间件,完成一个 「请求」 - 「响应」 的生命周期,之后我们的 Web 服务器将等待下一轮用户请求。
参考资料感谢下列优秀的 Laravel 研究资料:
http://blog.mallow-tech.com/2...
http://laravel-recipes.com/re...
http://www.cnblogs.com/sweng/...
https://www.dyike.com/2017/04...
http://www.cnblogs.com/wxw16/...
http://www.php.cn/php-weiziji...
https://segmentfault.com/a/11...
https://segmentfault.com/a/11...
https://blog.csdn.net/cDonDon...
https://segmentfault.com/a/11...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/28672.html
摘要:划下重点,服务容器是用于管理类的依赖和执行依赖注入的工具。类的实例化及其依赖的注入,完全由服务容器自动的去完成。 本文首发于 深入剖析 Laravel 服务容器,转载请注明出处。喜欢的朋友不要吝啬你们的赞同,谢谢。 之前在 深度挖掘 Laravel 生命周期 一文中,我们有去探究 Laravel 究竟是如何接收 HTTP 请求,又是如何生成响应并最终呈现给用户的工作原理。 本章将带领大...
摘要:应用实例所依赖的服务提供者可以在配置文件中的节点找到。完成所有服务提供者注册到应用实例后,应用实例执行启动方法引导项目启动。或内核接收到请求,加载服务提供者,同时,将请求分发给路由器执行。 这是一篇翻译文章,原文 Request Life Cycle of Laravel,译文 Laravel 请求生命周期 首发于个人博客,转载请注明出处。 当需要使用一个框架、工具或者服务时,在使用前...
摘要:请求处理阶段请求处理阶段首先是准备请求处理的环境,包括环境加载服务提供者注册等环节,然后将请求实例通过中间件处理及通过路由和控制器的分发控制,使得不同的请求通过相应的处理程序进行处理并生成响应的过程。 Laravel请求到响应的整个执行过程,主要可以归纳为四个阶段,即程序启动准备阶段、请求实例化阶段、请求处理阶段、响应发送和程序终止阶段。 程序启动准备阶段 服务容器实例化 服务容器的实...
摘要:因为为单个请求创建的环境将在请求过程完成后立即销毁。可以成为强大的性能增强器,提供了优雅的结构和代码使用方式。你可以使用此命令快速安装它,并访问官方网站获取更多信息。注意目前仅支持和。服务器不能使用。基准测试使用进行干净的测试。 Swoole 是针对PHP的生产级异步编程框架。它是一种用纯C语言编写的PHP扩展,它使PHP开发人员能够在PHP中编写高性能,可扩展的并发TCP,UDP,U...
摘要:是为开发的生产级异步编程框架。因为单个请求创建的环境在请求执行结束后会立即销毁。可以提供强大性能而则可以提供优雅代码结构使用。在使用这个包之前,请确保你的机器安装了正确的。建立并运行起来现在,你可以执行以下的命令来启动服务。 showImg(https://segmentfault.com/img/bVbaF89?w=1240&h=634); Swoole 是为 PHP 开发的生产级异...
阅读 620·2023-04-26 02:03
阅读 999·2021-11-23 09:51
阅读 1064·2021-10-14 09:42
阅读 1691·2021-09-13 10:23
阅读 890·2021-08-27 13:12
阅读 812·2019-08-30 11:21
阅读 980·2019-08-30 11:14
阅读 1001·2019-08-30 11:09