page contents

SWOOLE分布式框架之IOC容器构建

Swoole高效跟传统的web开发有什么区别,除了传统的LAMP/LNMP同步开发模式,swoole的异步开发模式是怎么样的。

attachments-2021-02-EZOIq1uU601cad1002a2d.png

一、swoole的运行模式

Swoole高效跟传统的web开发有什么区别,除了传统的LAMP/LNMP同步开发模式,swoole的异步开发模式是怎么样的。

1.1、传统web开发模式

PHP web开发采用的方式是LAMP/LNMP架构,即Linux、Nginx,Mysql和PHP。这里以nginx来举例,大致结构为:

attachments-2021-02-7unfNccZ601cad5753965.png

当请求进入时,web server将请求转交给PHP-FPM,PHP-FPM是一个进程池架构的FastCGI服务,内置PHP解释器。FPM负责解释执行PHP文件生成响应,最终返回给web server,展现至前端。PHP文件中实现了许多业务逻辑,包括Mysql和Nosql的访问,调用第三方应用等等。

这样的结构php-fpm和nginx的配合已经运行得足够好,但是由于php-fpm本身是同步阻塞进程模型,在请求结束后释放所有的资源(包括框架初始化创建的一系列对象),导致PHP进程“空转”(创建<-->销毁<-->创建)消耗大量的CPU资源,从而导致单机的吞吐能力有限。

每次请求处理的过程都意味着一次PHP文件解析,环境设置等不必要的耗时操作PHP进程处理完即销毁,无法在PHP程序中使用连接池等技术实现性能优化。

1.2、Swoole运行模式

针对传统架构的问题,swoole从PHP扩展出发,解决了上述问题,相比于传统架构,Swoole进程模型最大的特点在于其多线程Reactor模式处理网络请求,使得其能轻松应对大量连接。

除此之外的优点还包括:

全异步非阻塞,占用资源开销小,程序执行效率高

程序运行只解析加载一次PHP文件,避免每次请求的重复加载

1.3、使用swoole和传统php开发的缺点

1、更难上手。这要求开发人员对于多进程的运行模式有更清晰的认识

2、更容易内存泄露。在处理全局变量,静态变量的时候一定要小心,这种不会被GC清理的变量会存在整个生命周期中,如果没有正确的处理,很容易消耗完所有的内存。在php-fpm下,php代码执行完内存就会被完全释放。


二、注解机制

一般而言,在编程届中注解是一种和注释平行的概念,在解释注解之前我们需要先定义一下 注解 与 注释 的区别:

注释:给程序员看,帮助理解代码,对代码起到解释、说明的作用

注解:给应用程序看,注解往往充当着对代码的声明和配置的作用,为可执行代码提供机器可用的额外信息,在特定的环境下会影响程序的执行。

框架可以基于这些元信息为代码提供各种额外功能,本质上注解就是理解注解只是配置的另一种展现方式:

比如通过注解的方式实现权限的控制,就比配置文件当中配置要更加的方便

比如利用注解的方式配置路由、配置定时任务

现有的基于swoole的框架很多都是基于注解开发的,所以我们需要对注解机制有了解,接下来利用代码来实现下注解


三、容器

3.1、什么是容器?

容器 就是一个巨大的工厂,用于存放和管理 对象的生命周期,并且能够解决程序的依赖关系,实现解耦。

3.2简单的通过代码理解依赖注入

/**

* 耦合严重的写法

**/

**class** **db** {

 **public** **static** **function** **get_db**() {

 **return** **new** mysqli('127.0.0.1','user','pass','dbname',3306);

 }

}

**class** **post** {

 **private** $db;

**public** **function** __construct($db){

 //假设数据库驱动发生了变化呢?如果写死只能直接改动代码

 **$this**->db =**new** mysqli('127.0.0.1','user','pass','dbname',3306); }

 **public** **function** **get_post**($id){

 **return** **$this**->db->query('SELECT * FROM post WHERE id ='.$id);

 }

}

$post = **new** post();

$post->get_post(12);

/*

*依赖注入的方式

*/

**<?php**

**class** **db** {

 **public** **static** **function** **get_db**() {

 **return** **new** mysqli('127.0.0.1','user','pass','dbname',3306);

 }

}

**class** **post** {

 **private** $db;

 **public** **function** **set_db**(db $db){

 **$this**->db = $db;

 }

 **public** **function** **get_post**($id){

 **return** **$this**->db->query(select xx from xxx);

 }

}

$post = **new** post();

$post->set_db( db::get_db() ); //注入post类依赖的数据库连接对象,通过类名直接调用静态方法get_db

$post->get_post(11);

当没有Ioc/DI容器时

attachments-2021-02-iHbo97rC601cad7574e71.png

当有了IoC/DI的容器后,post类不再主动去创建db类了,如下图所示:

attachments-2021-02-j2YiFkBo601cad7dcf9d7.jpg

attachments-2021-02-jV3BJHdP601cad8548e4b.jpg

依赖注入:在A类中使用了B类的实例时,B对象的构造不是在A类某个方法中初始化的,而是在A类外部初始化之后以B类的对象传入进来。这个过程就是依赖注入。所需要的类通过参数的形式传入的就是依赖注入。

控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IOC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IOC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IOC容器了,通过IOC容器来建立它们之间的关系,控制反转意思是说将依赖类的控制权交出去,由主动变为被动。

3.3、为什么说在swoole当中使用容器更有意义?

传统的php框架没有常驻内存,因此每次请求进来都需要把用到的类都实例化一次,每次实例化都需要申请内存,当请求处理完之后又需要释放,具体请参看第一点,所以我们可以在server启动的时候就把类实例化预先放到内存中,减入对象的创建时间。

一个简单的bean容器

class BeanFactory{

 private static $container=[];

 public static function set(string $name,callable $func){

 self::$container[$name]=$func;

 }

 public static function get(string $name){

 if(isset(self::$container[$name])){

 return (self::$container[$name])();

 }

 return null;

 }
}


更多技术资讯,请继续关注六星教育社区-程序员编程技术分享交流学习高端论坛

attachments-2021-02-f7tebMD3601cad92f3118.jpg

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1320 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章