【PHP】PHP 微服务协程框架Swoft
<p><span style="font-size: 18pt"><strong> 简介</strong></span></p><p> 有了swoole这样强大的扩展之后,越来越多的框架都是基于swoole被开发出来,Swoft就是其中一款不错的PHP框架。Swoft 是一款基于 Swoole 原生协程的注解式框架,自带常驻内存以及 Swoole 其它功能的封装。swoft中内置了协程客户端。同时swoft里面有了很多新的概念,比如Aop等。</p>
<p> Swoft是基于Swoole开发的,如果不了解Swoole的可以看看我之前写的文章Swoole高性能框架。</p>
<p> 官网地址:<span style="color: rgba(83, 119, 202, 1)"><span style="color: rgba(83, 119, 202, 1)">https://www.swoft.org/</span></span></p>
<p> </p>
<p> </p>
<p><span style="font-size: 18pt"><strong> 使用Swoft框架注意事项</strong></span></p>
<p> 因为Swoft是基于Swoole,所以和普通的PHP框架还是很不一样的,有些是需要注意的。</p>
<p> 1.不要再代码中执行sleep()以及其他睡眠函数,这样会导致整个进程阻塞。</p>
<p> 2.不要使用exit/die函数,这样会导致worker进程直接退出。</p>
<p> 3.进程隔离需要注意的,当修改了全局变量的值,会不生效,因为全局变量在不同的进程中,内存空间是隔离的。使用Swoft框架需要了解进程隔离问题。不同的进程中PHP变量不是共享,即便是全局变量。如果不同的进程需要共享数据,可以使用Redis,Mysql,消息队列,文件,Swoole/Table,APCu(php自带的缓存扩展),shmget(进程通信(IPC)共享内存)等工具。同时不同进程的文件句柄也是隔离的,所以在A进程创建的Socker连接打开的文件在B进程内是无效的。</p>
<p> 4.进程克隆,当server启动时候,主进程会克隆当前进程状态,此后开始进程内的数据互相独立,互不影响。</p>
<p> 5.不要再控制器写基类来写公共的变量,这样会造成数据污染,当下一个请求进来依然会请求到这个变量,因为常驻内存并且单利所以不会释放掉。</p>
<p> 官方文档也有提示</p>
<p> <img src="https://img2020.cnblogs.com/i-beta/824470/202003/824470-20200325003445513-742024285.png"></p>
<p> </p>
<p> <span style="color: rgba(80, 88, 215, 1)">https://www.swoft.org/documents/v2/dev-guide/dev-note/</span></p>
<p> </p>
<p> </p>
<p><span style="font-size: 18pt"><strong>Swoft框架</strong></span><span style="font-size: 18pt"><strong>安装</strong></span></p>
<p> 安装环境要求:</p>
<p> 1. gcc版本大于等于4.8。</p>
<p> 2. PHP版本大于7.1。</p>
<p> 3. Composer包管理工具。</p>
<p> 4. 安装Redis异步客户端hiredis,在最新版本的Swoole4.2.6之后已经内置了,不需要安装。</p>
<p> 5. Swoole扩展,这个是必须的。</p>
<p> 6.链接迭代器依赖库pcre。</p>
<p> 7. Swoole需要开启协程和异步redis。</p>
<p> </p>
<p> 安装</p>
<div class="cnblogs_code">
<pre>git clone https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">github.com/swoft-cloud/swoft</span>
<span style="color: rgba(0, 0, 0, 1)">cd swoft
composer </span><span style="color: rgba(0, 0, 255, 1)">install</span>
<span style="color: rgba(0, 0, 255, 1)">cp</span> .<span style="color: rgba(0, 0, 255, 1)">env</span>.example .<span style="color: rgba(0, 0, 255, 1)">env </span>#<span style="color: rgba(0, 0, 0, 1)">编辑 .env 文件,根据需要调整相关环境配置</span></pre>
</div>
<p> 如果出现下面错误说明redis扩展没有,因为swoft需要redis扩展。</p>
<p><img src="https://img2020.cnblogs.com/i-beta/824470/202003/824470-20200325140746568-2098831349.png"></p>
<p>当然使用docker方式会更加简单,执行下面命令</p>
<div class="cnblogs_code">
<pre>docker run -p <span style="color: rgba(128, 0, 128, 1)">18306</span>:<span style="color: rgba(128, 0, 128, 1)">18306</span> --name swoft swoft/swoft</pre>
</div>
<p> </p>
<p><img src="https://img2020.cnblogs.com/blog/824470/202003/824470-20200325145502801-639597087.png"></p>
<p> </p>
<p> 在浏览器中输入 http://127.0.0.1:18306 就可以打开Swoft本地页面。</p>
<p> 关闭和开启运行命令 docker start/stop swoft</p>
<p> </p>
<p><span style="font-size: 18pt"><strong>Swoft目录及文件说明</strong></span></p>
<p>进入容器查看swoft目录</p>
<div class="cnblogs_code">
<pre>root@880c142615c3:/var/www/swoft# tree -L <span style="color: rgba(128, 0, 128, 1)">2</span><span style="color: rgba(0, 0, 0, 1)">
.
</span>|--<span style="color: rgba(0, 0, 0, 1)"> CONTRIBUTING.md
</span>|--<span style="color: rgba(0, 0, 0, 1)"> Dockerfile
</span>|--<span style="color: rgba(0, 0, 0, 1)"> LICENSE
</span>|--<span style="color: rgba(0, 0, 0, 1)"> README.md
</span>|-- README.zh-<span style="color: rgba(0, 0, 0, 1)">CN.md
</span>|--<span style="color: rgba(0, 0, 0, 1)"> app #应用目录
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Annotation #<code class="language-bash hljs">定义注解相关<span style="color: rgba(0, 0, 0, 1)">目录</span></code>
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Application.php
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Aspect
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> AutoLoader.php
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Common
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Console
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Exception
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Helper #<code class="language-bash hljs">助手函数</code>目录
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Http
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Listener #<code class="language-bash hljs">事件监听器目录</code>
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Migration
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Model #<code class="language-bash hljs">模型、逻辑等代码目录</code>
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Process
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Rpc #<code class="language-bash hljs">RPC服务代码目录</code>
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Task #任务投递管理目录,这里可以做异步任务或者定时器的工作
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Tcp
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> Validator
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> WebSocket #<code class="language-bash hljs">WebSocket服务代码目录</code>
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> bean.php
</span>|--<span style="color: rgba(0, 0, 0, 1)"> bin
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> bootstrap.php
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> swoft #<code class="language-bash hljs">Swoft入口文件</code>
</span>|--<span style="color: rgba(0, 0, 0, 1)"> composer.cn.json
</span>|--<span style="color: rgba(0, 0, 0, 1)"> composer.json
</span>|--<span style="color: rgba(0, 0, 0, 1)"> composer.lock
</span>|--<span style="color: rgba(0, 0, 0, 1)"> config
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> base.php
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> db.php
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> dev
</span>|--<span style="color: rgba(0, 0, 0, 1)"> database
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> AutoLoader.php
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> Migration
</span>|--<span style="color: rgba(0, 0, 0, 1)"> dev.composer.json
</span>|-- docker-<span style="color: rgba(0, 0, 0, 1)">compose.yml
</span>|--<span style="color: rgba(0, 0, 0, 1)"> phpstan.neon.dist
</span>|--<span style="color: rgba(0, 0, 0, 1)"> phpunit.xml
</span>|--<span style="color: rgba(0, 0, 0, 1)"> public
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> favicon.ico
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> image
</span>|--<span style="color: rgba(0, 0, 0, 1)"> resource #<code class="language-bash hljs">应用资源目录</code>
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> language
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> views
</span>|--<span style="color: rgba(0, 0, 0, 1)"> runtime <span style="color: rgba(0, 0, 0, 1)">#<code class="language-bash hljs">临时文件目录(日志、上传文件、文件缓存等)</code></span>
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> logs
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> sessions
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> swoft.command
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> swoft.pid
</span>|--<span style="color: rgba(0, 0, 0, 1)"> test #<code class="language-bash hljs">单元测试目录</code> <code class="language-bash hljs"></code>
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> apitest
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> bootstrap.php
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> run.php
</span>| |--<span style="color: rgba(0, 0, 0, 1)"> testing
</span>| `--<span style="color: rgba(0, 0, 0, 1)"> unit
`</span>--<span style="color: rgba(0, 0, 0, 1)"> vendor
</span>|--<span style="color: rgba(0, 0, 0, 1)"> autoload.php
</span>|--<span style="color: rgba(0, 0, 0, 1)"> bin
</span>|--<span style="color: rgba(0, 0, 0, 1)"> composer
</span>|--<span style="color: rgba(0, 0, 0, 1)"> doctrine
</span>|--<span style="color: rgba(0, 0, 0, 1)"> monolog
</span>|--<span style="color: rgba(0, 0, 0, 1)"> myclabs
</span>|--<span style="color: rgba(0, 0, 0, 1)"> nikic
</span>|-- phar-<span style="color: rgba(0, 0, 0, 1)">io
</span>|-- php-<span style="color: rgba(0, 0, 0, 1)">di
</span>|--<span style="color: rgba(0, 0, 0, 1)"> phpdocumentor
</span>|--<span style="color: rgba(0, 0, 0, 1)"> phpoption
</span>|--<span style="color: rgba(0, 0, 0, 1)"> phpspec
</span>|--<span style="color: rgba(0, 0, 0, 1)"> phpunit
</span>|--<span style="color: rgba(0, 0, 0, 1)"> psr
</span>|--<span style="color: rgba(0, 0, 0, 1)"> sebastian
</span>|--<span style="color: rgba(0, 0, 0, 1)"> swoft
</span>|--<span style="color: rgba(0, 0, 0, 1)"> symfony
</span>|--<span style="color: rgba(0, 0, 0, 1)"> text
</span>|--<span style="color: rgba(0, 0, 0, 1)"> theseer
</span>|--<span style="color: rgba(0, 0, 0, 1)"> toolkit
</span>|--<span style="color: rgba(0, 0, 0, 1)"> vlucas
`</span>-- webmozart</pre>
</div>
<p> </p>
<p><span style="font-size: 18pt"><strong>SwoftBean容器</strong></span></p>
<p> Bean容器是Swoft的核心,每一个Bean就是一个类对象的实例,容器就是一个工厂来存放和管理Bean。在HttpServer启动时候会扫描带有@Bean注解(下面会说)的类。传统的PHP是没有常驻内存的,每次请求都会重新初始化各种资源,每个对象也要重新实例化去申请内存,处理完请求后又被消耗,十分浪费资源。而Swoft在HttpServer启动后会将这些对象实例化并存放在内存中,下次请求就直接取出使用,减少对象创建资源的消耗。</p>
<p> Bean容器底层是一个BeanFactory管理容器(Container)。</p>
<p> 在启动Swoft过程中根据@Bean注解去获取类的实例,然后再将实例装载到Bean容器中,在需要的时候在根据命令去调用这些实例对象。下图就是这个过程示意图。</p>
<p> <img src="https://img2020.cnblogs.com/blog/824470/202004/824470-20200424145346555-827534431.png"></p>
<p> </p>
<p> </p>
<p><strong><span style="font-size: 18pt"><strong>Swoft</strong></span><span style="font-size: 18pt">注解(Annotations)机制</span></strong></p>
<p><strong> </strong>注解是Swoft里面很多重要功能特别是AOP,IoC容器的基础。熟悉Java的朋友应该更加了解注解。 </p>
<p><strong> </strong>那么注解是什么样呢?下面是Swoft的一部分代码<strong>,</strong>在类、方法或成员变量上方的注释部分就有注解。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">namespace App\Tcp\Controller;
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> App\Tcp\Middleware\DemoMiddleware;
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Swoft\Tcp\Server\Annotation\Mapping\TcpController;
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Swoft\Tcp\Server\Annotation\Mapping\TcpMapping;
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Swoft\Tcp\Server\Request;
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Swoft\Tcp\Server\Response;
</span><span style="color: rgba(0, 0, 255, 1)">use</span> <span style="color: rgba(0, 0, 255, 1)">function</span> <span style="color: rgba(0, 128, 128, 1)">strrev</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* Class DemoController
*
* @TcpController(middlewares={DemoMiddleware::class}) #这个就是注解
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> DemoController
{
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* @TcpMapping("list", root=true)
* @param Response $response
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> <span style="color: rgba(0, 0, 255, 1)">list</span>(Response <span style="color: rgba(128, 0, 128, 1)">$response</span>):<span style="color: rgba(0, 0, 0, 1)"> void
{
</span><span style="color: rgba(128, 0, 128, 1)">$response</span>->setData('allow command: list, echo, demo.echo'<span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p> 注解是什么呢?有什么作用呢?</p>
<p> 注解其实是通过反射把注释当成代码的一部分,PHP可以通过ReflectionClass来获取一个类的信息,从而了解类里的信息,比如获取类中的所有方法、成员变量,并包括私有方法等,并根据这些信息实现一些操作。像很多PHP框架,比如laravel框架就利用PHP的反射机制来实现依赖注入。</p>
<p> 其实注解是配置的另一种方式,这里注解就可以起到一个配置作用。比如定义路由,定义配置定时任务,权限控制等。</p>
<p> </p>
<p> 在Swoft中要是使用注解,需引入相关注解(Annotation)类,且必须以 <code>/**</code> 开始并以 <code>*/</code> 结束,否则会导致无法解析!</p>
<p> </p>
<p> </p>
<p><span style="font-size: 18pt"><strong>Aop切面编程</strong></span></p>
<p> Aop介绍</p>
<p> 1. Aspect(切面):通常是一个类,里面可以定义切入点和通知。</p>
<p> 2. JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用。</p>
<p> 3. Advice(通知):Aop在特定的切入点执行的增强处理,有before,after,afterReturning,afterThrowing,around。</p>
<p> 4. Pointcut(切入点):就是嗲有通知的连接点,在程序中主要体现为书写切入点表达式。</p>
<p> Swoft新版的Aop设计建立在PHP Parser上面。</p>
<p> PHP-Parser的项目主页是:<span style="color: rgba(85, 117, 200, 1)"><span style="color: rgba(85, 117, 200, 1)">https://github.com/nikic/PHP-Parser</span></span></p>
<p> </p><br><br>
来源:https://www.cnblogs.com/songgj/p/8684320.html
頁:
[1]