Swoft在PHPer圈中是一个门槛较高的Web框架,不仅仅由于框架本身带来了很多新概念和前沿的设计,还在于Swoft是一个基于Swoole的框架。Swoole在PHPer圈内学习成本最高的工具没有之一,虽然Swoft的出现降低了Swoole的使用成本,但如果你对Swoole本身了解不够深入,仍然很难避免栽进种种"坑"中。

考虑到这个现状,也为降低阅读难度,后续几个和Swoole联系较为密切的机制,笔者会调整写作思路,将文章的定位从 「帮助读者深入理解Swoft」 调整为 「帮助读者理解Swoft和Swoole」,叙述节奏也会放慢。

三种PHP应用的Web模型

LNMP模型

LNMP和LAMP是绝大多数PHPer最熟悉的基础Web架构,这里以常见的LNMP作为例子描述一个常见 无Swoole应用的构件组成:Nginx充当Webservice,PHP-fpm维护一个进程池去运行Web项目。

对比更古老的cgi模型,php-fpm已经引入了进程常驻的概念,避免每次请求创建并销毁进程的开销以及拓展加载的开销,但是每个请求仍然要执行PHP RINIT 与 RSHUTDOWN 之间的所有流程,包括重新加载一次框架源码以及项目代码,造成极大的性能浪费。

这种模型的优点是简单成熟和稳定,一次运行随后销毁 带来的开发便捷性是PHP能够流行起来的原因之一。市面上绝大多数PHP项目使用的都是基于该种架构的变体。

LNMP-with-Swoole模型

LNMP-with-Swoole 是 LNMP的一种变体,其在LNMP的基础上引入了Swoole组件。

和PHP-fpm一样,Swoole有一套自己的进程管理机制。但由于代码变得高度常驻和编程思维需要从同步到异步的转变,所以Swoole和传统的基于PHP-fpm的Web框架亲和度很低,即使是适配升级过的老式Web框架,目前在Swoole上运行的表现往往并不好。

因此出现了这在这种折中方案,并没有直接将原有PHP代码运行在Swoole中,而是使用Swoole搭建了一个服务,系统通过接口与Swoole通信,从而为Web项目补充了异步处理的能力。我称呼这种同时使用PHP-fpm和Swoole的系统为 半Swoole应用。因为接入简单,所以是绝大多数现有项目优先考虑的Swoole接入方案。

LNMP-with-Swoole模型虽然引入了Swoole和异步处理能力,但是核心还是php-fpm,实际上还远远没有发挥出Swoole的真正优势。

Swoole-HTTP-Server模型

Swoole-HTTP-Server和LNMP-with-Swoole相比有巨大的变化,这种模型中充当WebServer角色的构件不仅仅有nginx,应用本身也包含了一个内建WebServer,不过由于Swoole Http Server不是专业的Http Server,对Http的处理不完善 ,因此仍然需要使用Nginx作为静态资源服务器以及反代,Swoole Http Server仅仅处理PHP相关的Http流量。

一方面由于Swoole已经包含了WebServer,不再需要实现cgi或者fast-cgi的通用协议去和WebServer通信,另一方面Swoole有自己的进程管理,因此PHP-fpm可以直接被去除了。对于PHP资源而言,在这种模型中,Swoole Http Server的地位相当于传统模型中的nginx和PHP-fpm之和。

一次加载常驻内存,不同的请求间基本上复用了onRequest以外的所有流程,使得每个请求的开销大大降低;异步IO的特性使得这种模型吞吐量远远高于传统的LNMP模型。另外相对于独立的Swoole服务,内嵌在Web系统中的Swoole使用更加的直接方便,支持更好。

Swoft和Swoole的关系是什么?

Swoole是一个异步引擎,核心是为PHP提供异步IO执行的能力,同时提供一套异步编程可能会用到的工具集。

Swoole-HTTP-Server是Swoole的一个组件,是SwooleServer中的一种,提供了一个适合Swoole直接运行的HttpServer环境。

Swoft一个现代的Web框架,和Swoole亲和性高,同时也是上面提到的Swoole-HTTP-Server模型模型的一个实践。

Swoft管理着该Web模型中的Swoole,以及Swoole-Http-server,对开发者屏蔽swoole的种种复杂操作细节,并作为一个Web框架向开发者提供各种Web开发需要用到的路由,MVC,数据库访问等功能组件等。

Swoft是如何使用Swoole的?

最核心的就是HttpServerr以及RpcServer

Http服务器

Swoft直接使用的是Swoole内建的\Swoole\Http\Server,它已经处理好所有Http层面的所有东西,我们只需要关注应用本身,我们来看一下Http服务几个重要生命周期点。

swoole启动前

这个阶段进行的行为有几个特征

1.基础bootstrap行为:如必须的常量define,composer加载器引入,配置读取。

2.需要生成被所有worker/task进程共享的程序全局期的对象,如Swoole\Lock,Swoft\Memory\Table的创建。

3.启动时,所有进程中合计只能执行一次的操作:如前置Process的启动。

4.Bean容器基本初始化,以及项目启动流程需要的coreBean的加载。

这块涉及东西比较杂,为控制篇幅后续用单独文章介绍。

和Http服务关系最密切的进程是Swoole中的Worker进程(组),绝大部分业务处理都在该进程中进行。

对于每个Swoole事件,Swoft都提供了对应的Swoole监听器(对应@SwooleListener注解)作为事件机制的封装。要理解Swoft的HttpServer是如何在Swoole下运行的我们重点需要关注下两个在两个Swoole事件swoole.workerStart和swoole.onRequest。

swoole.workerStart事件

workerStart事件在TaskWorker/Worker进程启动时发生,每个TaskWorker/Worker进程里都会执行一次。

这是个关键节点,因为swoole.workerStart回调之后新建的对象都是进程全局期的,使用的内存都属于特定的Task/Worker进程,相互独立。也只有在这个阶段或以后初始化的部分才是可以被热重载的。

事件底层关键代码如下:

Swoft\Bootstrap\Server\ServerTrait.php

/**

* @param bool $isWorker

* @throws \InvalidArgumentException

* @throws \ReflectionException

*/

protected function reloadBean(bool $isWorker)

{

BeanFactory::reload();

$initApplicationContext = new InitApplicationContext();

$initApplicationContext->init();

if($isWorker && $this->workerLock->trylock() && env('AUTO_REGISTER', false)){

App::trigger(AppEvent::WORKER_START);

}

}

这里做的事情有3点

初始化Bean容器:

上文中的BeanFactory::reload();就是Swoft的Bean容器初始化入口,注解的扫描也是在此处进行(实际上这个说法并不准确,Bean容器真正的初始化阶段在Swoole Server启动前的BootStrap阶段就已经进行了,只不过那时进行的是少部分初始化,相对swoole.workerStart中的初始化的Bean数量,比重很小)。在workerStart中初始化Bean容器是Swoft可以热更新代码的基础。

初始化的应用上下文

initApplicationContext->init()会注册Swoft事件监听器(对应@Listener),方便用户处理Swoft应用本身的各种钩子。随后触发一个swoft.applicationLoader事件,各组件通过该事件进行配置文件加载,http/rpc路由注册。

服务注册

具体内容会在服务治理章节讲述。

swoole.onRequest事件

每个http请求到来时仅仅会触发swoole.onRequest事件。

框架代码本身都是由大量进程全局期和少量程序全局期的对象构成,而onReceive中创建的对象譬如$request和$response都是请求期的,随着http请求的结束而回收。

事件底层关键代码如下:

/**

* Do dispatcher

*

* @param array ...$params

* @return \Psr\Http\Message\ResponseInterface

* @throws \InvalidArgumentException

*/

public function dispatch(...$params): ResponseInterface

{

/**

* @var RequestInterface $request

* @var ResponseInterface $response

*/

list($request, $response) = $params;

try {

// before dispatcher

$this->beforeDispatch($request, $response);

// request middlewares

$middlewares = $this->requestMiddleware();

$request = RequestContext::getRequest();

$requestHandler = new RequestHandler($middlewares, $this->handlerAdapter);

$response = $requestHandler->handle($request);

} catch (\Throwable $throwable) {

/* @var ErrorHandler $errorHandler */

$errorHandler = App::getBean(ErrorHandler::class);

$response = $errorHandler->handle($throwable);

}

$this->afterDispatch($response);

return $response;

}

beforeDispatch($request, $response):

设置请求上下文,并触发一个swoft.beforeRequest事件。

RequestHandler->handle($request):

执行各个 中间件 和请求对应的 action,具体处理可以参考RPC章节,原理基本相同。

$afterDispatch($response):

整理http响应报文发送客户端并触发swoft.resourceRelease(详情在连接池一文中提及)事件和swoft.afterRequest事件

总的来说,纵观这几个生命周期点你需要搞清楚几件事:

Swoole的worker进程是你绝大多数Http服务代码的运行环境。

一部分初始化和加载操作在swoole的server启动前完成,一部分在swoole.workerStart事件回调中完成,前者无法热重载但可能被多个进程共享。

初始化代码只会在系统启动和Worker/Task进程启动时执行一次, 不像PHP-fpm每次请求都会执行一次,框架对象也不像PHP-fpm会随请求返回而销毁。

每次请求都会触发一次swoole.onRequest事件,里面就是我们的请求处理代码真正运行的地方,只有这事件内产生的对象才会在请求结束时被回收。

RPC服务器

swoft php怎么样,[原创]Swoole和Swoft的那些事 (Http/Rpc服务篇)相关推荐

  1. php定时任务sw,[原创]Swoole和Swoft的那些事(Task投递/定时任务篇)

    Swoft的任务功能基于Swoole的Task机制,或者说Swoft的Task机制本质就是对SwooleTask机制的封装和加强. 任务投递 //Swoft\Task\Task.php class T ...

  2. swoft php怎么样,Swoft源码之Swoole和Swoft的分析

    这篇文章给大家分享的内容是关于Swoft 源码剖析之Swoole和Swoft的一些介绍(Task投递/定时任务篇),有一定的参考价值,有需要的朋友可以参考一下. 前言 Swoft的任务功能基于Swoo ...

  3. 微服务研究 - Swoole框架-Swoft初探

    微服务研究 - Swoole框架-Swoft初探.没有swoole之前,php一直被"誉"为世界上最好的语言.swoole横空出世后,php就成了宇宙最好的语言了... swoft ...

  4. swoole 框架swoft使用

    再简单的东西,再简单的流程,过一段时间不涉足,也就忘记了.用的时候又要去找资料,然后再慢慢会记忆恢复.所以还是记下来的为好. swoft官网,https://www.swoft.org,swoole官 ...

  5. php swoft 应用,Swoole 在 Swoft 中的应用

    date: 2017-12-14 21:34:51 title: swoole 在 swoft 中的应用 上一篇 blog - swoft 源码解读 反响还不错, 不少同学推荐再加一篇, 讲解一下 s ...

  6. Swoft 2.x 微服务基础(Consul、RPC 服务发现、限流与熔断器)

    本篇概要: 1. Swoft 服务注册与发现: 1.1 Consul 概况: 1.2 在 Consul 注册服务.反注册: 1.2.1 注册服务: 1.2.2 反注册: 1.3 健康检查: 1.4 服 ...

  7. Swoft Rpc调用(一) Rpc服务初始化

    Swoft框架的初始化 Swoft初始化有六个步骤 ENV环境文件初始化 注解信息扫描收集 配置初始化 注册类到bean容器 收集事件监听器 启动console控制台,启动相应的服务 官方文档 而Rp ...

  8. (原创)面向对象的系统对接接口编写。第4篇

    接上一篇:http://www.cnblogs.com/mazhiyuan/p/5224050.html 这篇开始写Post和Get请求的布局. 我们就以新闻模块来举例吧.其它的模块,比如用户啦,比如 ...

  9. Swoft 踩坑笔记一 - 安装Swoft并启动

    emmmmmmmm,一开始接触我也是一脸懵逼啊!不过幸运的是我有开发组的大佬可以请教,所以......还是一脸懵逼啊! 因为常规FPM框架的技术在swoft里就占那么一丢丢,其余的都没见过啊. 目前我 ...

最新文章

  1. 通知:正式迁移至新博客
  2. 让织梦CMS的后台编辑器支持优酷视频
  3. 两个ListBox的相互操作
  4. BitAdminCore框架更新日志20180529
  5. mac vim 无颜色 增加颜色
  6. p1198bzoj1012 最大数
  7. android tabspec英文自动大写问题,为什么不能在drawable下访问xml文件?所有的
  8. java飞机大战子弹怎么修改_java改版飞机大战源码
  9. 多元线性回归矩阵求导
  10. 深入浅出TensorFlow2函数——tf.data.Dataset.padded_batch
  11. 解决Git使用出现git@githubcom Permission denied (publickey)
  12. 互联网家谱受到追捧,传统修谱方式面临淘汰,数字家谱:好用
  13. Unity场景渲染之自发光材质
  14. md语法语法_PHP –语法概述
  15. 16、基于51单片机智能浇花自动浇水灌溉土壤湿度检测报警系统设计
  16. matlab 多项式拟合EXCEL中复杂数据
  17. 连续被爆押金退款难  共享汽车会否走向和共享单车一样的宿命?
  18. 全面解析jQuery $(document).ready()和JavaScript onload事件
  19. 16位字长的计算机,十六位字长的计算机是指计算机16位十进制数的计算机吗
  20. AndroidQ(10)黑暗模式适配

热门文章

  1. 使用ubuntu 10.04中的中文乱码问题解决
  2. 【转载】Linux等类Unix系统学习用书那点事儿!
  3. Linux 命令(74)—— top 命令
  4. 在大量数据迁移期间oracle学习笔记
  5. Eclipse查看源码乱码问题
  6. repo 的几个使用理解
  7. [DEncrypt] DESEncrypt--加密/解密帮助类 (转载)
  8. Clojure Web 开发 (一)
  9. const的修饰规则
  10. Spring安全依赖查找