关于thinkphp-swoole的学习以及相关周边知识补充

方滴云WEB2022-02-06 21:25

关于开发环境

在谈及swoole之前,首先说下我们运行的开发环境。因为swoole目前不支持windows,对于我这种不中意MAC的用户,linux当然是首选了。

因为日常还是使用windows的,所以综合取舍后,选择了WSL2,通过虚拟机,WSL2作为子系统,很好的实现了linux与windows的共存。

在系统选择方面,可能我更推荐ubuntu。因为其商业性更好,同时生态也相对完善,特别是对于新手而言,会更加适合好些。不过,做为一个爱折腾的人,我不太喜欢走别人的路,我最终的选择是Debian。

WEB环境方面,自己一个个动手安装,确实很烦人,而且还需要各种工具。并且我也没有做图形化,关于图形化,我会考虑后面弄个本本专业玩它再说。所以,WEB环境搭建,我借助了宝塔。

通过宝塔主要安装的应用有nginx、mysql、php(拓展fileinfo、reids、swoole)、redis、supervisor。因为还用了nodejs,所以还安装了nodejs版本管理器以及pm2管理器。因为我nodejs只是做调试的,所以PM2并没怎么使用。为了方便数据库管理,还安装了phpMyAdmin。

关于软件安装、环境配置这些东西,网上教程还是非常丰富的。大家只要认真找,仔细看、多尝试,搞定它并不难。有两点值提醒下,第一对于网上的教程一定要认真看,不要随便尝试;第二遇到错误万不要慌乱,特别是对于我这种英文功底不好的开发者,更是要静下心。


关于swoole

提及swoole就不得不说php这门语言了,爱他的人说倔是“世界上最了的语言”,但是在鄙视链上,却总有关于“2020 php凉了吗?”、“2021 php凉了吗?”这样的热论。但是,不管如何讨论,php还是稳稳的存活在互联网的各个角落。

当然,对于php的攻击言论,更多是源于其性能问题吧。从php7开始,性能已经得到了数倍的提升,特别是如今php8的发布,更是在性能上下足了功夫。我一直觉得,没有最好的语言,但有最好的语言er,只要我们用熟悉的语言最优的解决问题,就是最好的。

swoole让php在协程方面有了更多的可能。通过Swoole ,phper可以编写高性能高并发的 TCP、UDP、Unix Socket、HTTP、 WebSocket 等服务,让 PHP 不再局限于 Web 领域。Swoole 可以广泛应用于互联网、移动通信、云计算、 网络游戏、物联网(IOT)、车联网、智能家居等领域。

当然 ,基于swoole框架的开发,对于我这种菜鸟基本是不可能的,我们用好前辈们造的工具解决好问题就可以啦。

这些年关于php的开发,我一直使用的thinkphp,tp官方也有相关的拓展程序think-swoole,简易教程手册中有,当然也可以看这个入门教程。https://www.kancloud.cn/thinkphp/think-swoole/722895

当然,如果您想更加深入的了解,建议看下think-swoole下面的readme,这里的介绍虽然有一些地方不太好理解,但是信息量更多大。


1. 启动Swoole HTTP服务

使用swoole的第一个应用场景,就是让开发的应用直接部署到swoole上,从而享受性能的数倍提升。如WEB服务器使用的是nginx,可以通过反向代理将请求转发到swoole上。更多详细的介绍与配置说明,可以参考上面的入门教程。


2. 启动Swoole Server

通过think-swoole拓展,我们的第二个应用场景就是快速启动一个swoole服务,包含websocket、 http 、socket服务。如果config\swoole-server.php的配置不能满足您的需求,我们还可以自定义服务类。

启用自定义服务类后,在config\swoole-server.php中填写'swoole_class' => 'app\http\Swoole'即可。其他的配置全部失效,可以清除了。从教程来看,这个自定义服务类,其实我也还有很多地方没有搞明白。因为爬了些坑,所以这里简单列举下。

1)我也是按教程写的自定义服务类,但是启动时一直报错,大致的意思是说我有一些回调函数没有实现。于是我按要求把要求的回调配置进来进就好了;

2)关于配置项,明明说的“支持swoole所有的参数,以及支持使用闭包方式定义相关事件回调”,但是关于监控文件更新的功能,好像我并没有配置成功;

3)其他的配置项目,比如pid_file与pid_log我到是实现了,如下图所示;image.png

因为我之前也玩过workman,所以看到这个think-swoole到也是有几分亲切,于是我就简单的玩了下他的websoket与http服务。

http的相对比较简单,就是按教程说的,访问的时候展示Hello Swoole # 随机数。但是对于chrome浏览器,会自动请求一次favicon.ico。如果没有它会报一次错,另外我后面还有业务要处理,所以这个请求我要识别出来 ,同时也学习了下它参数的处理,大致如下:

image.png

执行后结果就是这样的,没有什么惊讶的。

image.png

然后我还是实现了多个用户。后台可以实现指定用户发送与所有用户发送消息。这里的麻烦是,不论指定用户发送还是群发都要把当前在线的用户的fd拿到。

前端好实现,用户后台登录后,会有一上uid登录的时候传过来就可以把uid与fd进行绑定了,后续想发给谁,可以通过uid去查fd,为了简单起见,我在前端用localstorage随便存了个uid,当然不能重了。

关于这个uid重的问题,这里是有可能的,因为同一用户可以进行多端登录,所以这个时候关uid是搞不定的,还要配合使用用户的终端标识。这里只是玩玩,我们就不能那么较真了,原理都是一样的,当然实现可能还有很多技术债,不过没有关系,有路子了,可以慢慢偿的。

现在的问题在于服务端要如何处理,最初的幼稚的想法是通过存一个变量来放它,不是说文件常驻内存不释放么,可能我的理解有误,当然也可能是操作不当吧,最终失败了。

思来想去,最后想到的就是数据库或缓存做存储吧。

如果是真实的聊天环境可能是要考虑存数据库吧,不过我们这里只是做调试,所以我使用缓存了,我的缓存用的是redis,当然用文件缓存可能更加直观。

image.png

执行后,大致就是上面的样子了,其实也很简单的,不过免得忘了,这里帖一个简单的代码吧。

image.png

服务启动时,首先把原来的缓存清掉。

image.png

接收到数据后,如果有uid把绑定关系存缓存,如果有msg就给所有的人发消息,消息内容就是当前用户的msg。image.png

连接断开时,把绑定关系删除,并更新缓存。这里http请求,每次重新之前都会走进来的。

3. 定时器

定时器可以很方便的做帮我们做重复执行的任务,配置文件在config/timer.hp中,可以定义的参数有“秒 分 时 日 月 星期几”,还是挺实用的。配置在config/swoole.php中开启即可。

image.png

具体实现的测试代码如下 :

image.png

我的配置是”'*/5 * * * * *' => '\\app\\lib\\Timer'“跑起来后,大概是这样的。

image.png

我这里的要求每5S执行一次,但是如果执行时间大于5S会按具体的时间跑,但是跑完后,他会自己把时间追回来。当然这种情况,理论是不会存在的,所以不用在意。

4.异步任务

记得之前有一个项目,大概是生成一个合同,这个合同是几个pdf文件 ,要等他们生成完了,再给用户返回,因为执行时间有点长,所以上帝等的,多多少少有一点不耐烦。有了这个东西好了,根本不用等呀。下面我们来玩下它。

我们先来实现异步任务接口,代码(README里的代码可能没有更新。我没有跑起来。看源码改了下大致如下 。

image.png

异步任务实现后,我们去控制器里进行下任务投递。

image.png

在控制器中完成任务投递后,我们就可以跑的试下了。大致结果如下;

image.png

5. 消息列队

最后我们来聊聊消息列队,其配置文件在config/quequ.php,具体的配置可以参考官方手册 ,我这里用的是redis,具体如下。

image.png

下面我们来定义一个消息列队,具体的入门手册看这里:https://github.com/top-think/think-queue/tree/2.0,这个是针对tp5.1的。

image.png

创建任务类后,我们去控制器里发布一下。

image.png

具体我们可以在redis中查看下数据情况,开始redis中没有数据,任务发布后,有一条记录,4S后消息被消费了,redis中数据也被清掉了。还可以通过get key来查找具体的键的值。

image.png

任务发布后,我监听下任务,如下图:

image.png

至些,这几天的学习笔记 就算做完了,当然,还有更多的试验要做。


【20220206补充】

今天在调试时候,因为代码有错误,所以错误的消息列队都压到了redis中了。如下图所示


此时即使更正了代码,但是当监听启动时,之前的错误依然会一直缠绕。大致如下图所示:


这个时候,其实只要通过执行命令“flushall”刷新清除redis中的数据就可以了。