Easyswoole学习笔记,快速上手

EasySwoole

EasySwoole 是一款基于Swoole Server 开发的常驻内存型的分布式PHP框架,专为API而生,摆脱传统PHP运行模式在进程唤起和文件加载上带来的性能损失。EasySwoole 高度封装了 Swoole Server 而依旧维持 Swoole Server 原有特性,支持同时混合监听HTTP、自定义TCP、UDP协议,让开发者以最低的学习成本和精力编写出多进程,可异步,高可用的应用服务。

大部分功能类,都以单例模式为主
文章中代码内的反斜杠统一改成了正向斜杠(WordPress转义会导致反斜杠不显示)

基础知识

1.CLI命令

相关文档:http://www.easyswoole.com/QuickStart/command.html

2.异步任务

相关文档:http://www.easyswoole.com/Components/Component/task.html#%E4%BB%BB%E5%8A%A1%E6%A8%A1%E7%89%88

任务模板用于执行异步任务,调用方式如下:

$task = EasySwooleEasySwooleTaskTaskManager::getInstance();

// 投递异步任务
$task->async(new CustomTask(['user' => 'custom']));

// 投递同步任务
$data = $task->sync(new CustomTask(['user' => 'custom']));

3.框架启动流程、相关常量

相关文档:http://www.easyswoole.com/FrameDesign/start.html

4.全局事件

相关文档:http://www.easyswoole.com/FrameDesign/event/bootstrap.html

ServerManager是 EasySwoole 框架中,用于全局存储 Swoole 对象实例 所用的一个单例对象。

Core 是 EasySwoole 框架中核心的基础架构对象,这是一个单例对象。

bootstrap 事件允许在框架未初始化之前,先进行初始化其他需要的业务代码。该事件是在 EasySwoole 3.2.5版本之后 新增的。 (项目目录下的bootstrap.php文件中进行操作)

以下事件在项目目录下的EasySwooleEvent.php文件中进行定义:

  • bootstrap事件,框架初始化之前触发
  • Initialize 事件,框架初始化触发的事件,可以在这里加载配置文件、初始化自定义进程、初始化异步任务;
  • MainServerCreate 事件,主服务创建事件,可以在这个加载需要配合服务的一些事件;
  • OnRequest 事件,收到请求事件
  • AfterRequest 事件,请求方法结束后执行的事件
程序全局期
在 EasySwoole 框架根目录的 bootstrap.php 文件和 EasySwooleEvent.php 文件中的 initialize 事件函数中创建好的对象,我们称之为程序全局生命周期对象。这些变量只要没有被作用域销毁,在程序启动后就会一直存在,直到整个程序结束运行才会销毁。

5.依赖注入

相关文档:https://www.easyswoole.com/Components/Component/ioc.html

注入的全局的事件回调的键名:https://github.com/easy-swoole/easyswoole/blob/3.x/src/SysConst.php

6.配置文件

相关文档:http://www.easyswoole.com/QuickStart/config.html

<?php

$instance = EasySwooleEasySwooleConfig::getInstance();

// 获取配置 按层级用点号分隔
$instance->getConf('MAIN_SERVER.SETTING.task_worker_num');

// 设置配置 按层级用点号分隔
$instance->setConf('DATABASE.host', 'localhost');

// 获取全部配置
$conf = $instance->getConf();

// 用一个数组覆盖当前配置项
$conf['DATABASE'] = [
    'host' => '127.0.0.1',
    'port' => 13306
];

// 加载指定路径的配置文件
$instance->loadFile($filePath,bool $merge = true):bool

// 加载指定目录下的所有配置文件
$instance->loadDir(string $dirPath, bool $merge = true):bool

// 加载指定路径的环境配置
$instance->loadEnv(string $file,bool $merge = true):bool

// 加载指定的配置数组
$instance->load($conf);

7.自定义进程

相关文档:http://www.easyswoole.com/Components/Component/process.html

相关文档:http://www.easyswoole.com/Other/process.html

创建一个自定义进程,需要定义一个进程类继承EasySwoole/Component/Process/AbstractProcess。

在 EasySwoole 全局的 mainServerCreate 事件中进行进程注册

原理
onPipeReadable在自定义进程创建后,变成进程收到消息事件的回调函数。运行过程中是通过Event Loop来触发的
区别
Easywoole的异步任务组件也是基于多进程实现,往指定的进程池投递一个任务,自定义进程则是由自己实现全部业务逻辑

8.自定义异常处理

相关文档:http://www.easyswoole.com/BaseUsage/trigger.html

9.自定义事件

相关文档:http://www.easyswoole.com/BaseUsage/event.html

10.定时器

相关文档:http://www.easyswoole.com/Components/Component/timer.html

HTTP服务

1.控制器

所有控制器都是EasySwooleHttpAbstractInterfaceController的子类,EasySwoole 使用了对象池复用模式,降低对象创建、销毁的开销,注入 request 和 response 对象来完成客户端与服务端之间的交互。

  • onRequest,所有控制器请求都会先经过该方法
  • onException,当执行控制器方法抛异常时会调用该方法
  • afterAction,当 action 执行结束后调用该方法
  • actionNotFound,当请求方法未找到时,自动调用此方法
  • gc,在 afterAction 方法执行完后调用
  • 只有第一次请求时才会调用构造函数
  • 对象池模式只重置非静态 public 属性
  • 对象池复用模式只针对单一进程,多个 worker 进程不共享
  • 文件夹、文件、类名为大驼峰,变量与类方法小驼峰(规范)
  • action 返回的字符串将会被 url 解析规则以及 route 路由规则解析
  • 两个 action 的 return 不能互相调用,否则将导致死循环

2.Request 对象

Request 对象在系统中以单例模式存在,自收到客户端 HTTP 请求时自动创建,直至请求结束自动销毁。Request 对象完全符合 PSR-7 中的所有规范。

相关文档:http://www.easyswoole.com/HttpServer/request.html

3.Response对象

Response 对象在系统中以单例模式存在,自收到客户端 HTTP 请求时自动创建,直至请求结束自动销毁。

相关文档:http://www.easyswoole.com/HttpServer/response.html

4.路由

静态路由:http://www.easyswoole.com/HttpServer/staticRoute.html

动态路由:http://www.easyswoole.com/HttpServer/dynamicRoute.html

5.数据验证

验证码组件:http://www.easyswoole.com/Components/verifyCode.html

相关文档:http://www.easyswoole.com/Components/Validate/validate.html

6.全局变量

EasySwoole 在 spl 包中,实现了一个 SplContextArray,并在主进程的位置,替换了这些全局变量,使得这些数据的访问是安全的,并在请求结束后自动清理。从而我们可以在使用一些 FPM 环境下的组件包时没有影响。

相关文档:http://www.easyswoole.com/HttpServer/global.html

7.部署上线

部署时,可以通过Nginx反代理进行动静分离,静态文件由Nginx返回,动态接口则反代理内部接口。

server {
    root /data/wwwroot/;
    server_name local.swoole.com;
    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "keep-alive";
        proxy_set_header X-Real-IP $remote_addr;
        if (!-f $request_filename) {
             proxy_pass http://127.0.0.1:9501;
        }
    }
}

组件库 

1.连接池

相关文档:http://www.easyswoole.com/Components/Pool/introduction.html

  • EasySwoole/Pool/Config,连接池配置
  • EasySwoole/Redis/Config/RedisConfig,Redis连接配置
  • EasySwoole/Pool/Manager,连接池管理

2.ORM

Orm自带连接池,因此继承了EasySwoolePoolConfig,并且父级继承了EasySwooleSplSplBean具有对类属性快速赋值的操作。

  • Config,数据库和连接池的一些配置
  • Connection,数据库连接池的相关操作,基于连接池实现的连接类
  • DbManager,数据库连接管理器

模型定义:http://www.easyswoole.com/Components/Orm/definitionModel.html

相关文档:http://www.easyswoole.com/Components/Orm/install.html

3.回收

相关文档:http://www.easyswoole.com/Components/Pool/whyUsePool.html#%E8%BF%9E%E6%8E%A5%E6%B1%A0%E6%95%B0%E9%87%8F%E5%A6%82%E4%BD%95%E8%AE%BE%E7%BD%AE

  • defer方法将会在本次请求协程退出的时候自动回收
  • invoker是闭包函数方式 一次运行完马上自动回收
  • get方式 就是我们伪代码的方式 需要自己回收
同一个协程调用多次defer获取到的会是同一个数据库连接,不会出现多次defer获取多个数据库连接的情况
easyswoole中,需要根据进程来看,每个进程*连接池配置数量=总数量,比如easyswoole中worker进程为8,那你设置20个,那就是20*8=160的总数

3.上下文管理器

在Swoole中,由于多个协程是并发执行的,因此不能使用类静态变量/全局变量保存协程上下文内容。使用局部变量是安全的,因为局部变量的值会自动保存在协程栈中,其他协程访问不到协程的局部变量。

因Swoole属于常驻内存,在特殊情况下声明变量,需要进行手动释放,释放不及时,会导致非常大的内存开销,使服务宕掉。

ContextManager上下文管理器存储变量会自动释放内存,避免开发者不小心而导致的内存增长。

在协程的上下文内设置的key不会和其他协程产生冲突

相关文档:http://www.easyswoole.com/Components/Component/context.html

SplContextArray
实现了Array相关接口的协程安全自定义类,实例化的对象可以直接当做数组进行使用

4.热重启

相关文档:http://www.easyswoole.com/Components/fileWatcher.html

相关文档:https://www.easyswoole.com/Components/hotReload.html

5.文件操作组件

相关文档:http://www.easyswoole.com/Components/Help/file.html

6.错误视图

相关文档:http://www.easyswoole.com/Components/whoops.html

7.动态更新连接池

Easyswoole学习笔记,快速上手,持续记录
动态更新连接池

注意的几个地方:

  • worker进程挂掉之后,需要重新加载连接池,如果连接池已经发生改变了,新加载的连接池需要同步更新最新的状态。所以需要将连接池初始化的过程添加到onWorkerStart事件里。
  • 数据库连接池配置信息需要存放在共享内存里,这样可以保证一个worker修改后,其他的worker进程都能同步到这个状态。
  • 更新频率的问题,假设上次同步还未完成,开始了第二次更新?该如何处理。

思考:

  • 自定义进程、Worker进程、Task进程,都需要同步更新
  • Worker进程异常退出,被重启之后也需要同步更新
  • 上次更新还没结束,再次更新,防止冲突
  • 单个进程更新的过程中,需要防止重新更新
  • Worker进程异常退出,重启之后,要同步最新的更新标识和记录
数据库切换方案
如果是同一个服务器上面的不同数据库,那么直接use就好了。

8.定时任务

通过定时任务去异步处理任务,需要考虑的问题是:上一次操作没结束,又开始了下一次操作。

9.Ghostscript

Ghostscript是一款自由软件,也是一款用于解释和渲染PostScript和PDF文件的解释器。它可以将PostScript和PDF文件转换为其他格式,如图像文件、文本文件和PDF文件等。

gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dFIXEDMEDIA  -dDEVICEWIDTHPOINTS=288 -dDEVICEHEIGHTPOINTS=446  
-dPDFFitPage -q -dCompatibilityLevel=1.4  -sOutputFile="/home/Log/565656.pdf" 
./Log/test.pdf ./Log/test.pdf ./Log/test.pdf

安装GS:

yum install ghostscript

10.xpdf/pdfinfo

xpdf是一款开源的PDF文档查看器,它提供了多种PDF文档的浏览和操作功能。其中,bin64/pdfinfo是xpdf工具包中的一个命令行工具,用于获取PDF文档的元数据信息。

pdfinfo可以显示PDF文档的标题、作者、主题、关键字、创建和修改日期、页数、页面尺寸等信息。使用pdfinfo命令可以在命令行中快速查看PDF文档的元数据信息。

安装xpdf:

yum install xpdf

11.Debian镜像源

修改服务器,/etc/apt/sources.list

deb https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free
deb-src https://mirrors.tuna.tsinghua.edu.cn/debian/ buster main contrib non-free

然后运行apt-get update,更新镜像源。