学习Swoole之如何避免成为被坑哭的程序员

很多刚从传统fpm模式转到swoole内存常驻模式的phper,总会觉得内心委屈,甚至想哭,原因swoole总会让你怀疑人生,这真的是我之前所认知的那个php语言吗?怎么那么坑啊。

swoole下常见的”坑”

  • 为何全局变量无法共享呢

    例如,在以下代码中

    1. $http = new swoole_http_server("127.0.0.1", 9501);
    2. $http->on("request", function ($request, $response) {
    3. static $i;
    4. $response->end($i);
    5. $i++;
    6. });
    7. $http->start();

    就会有人发现在swoole下static $i 和在fpm下所理解的输出不一致。这是在于出现了进程克隆,而每个进程之间的数据都是不一致的。

  • echo var_dump 无法输出到浏览器(http响应)

    我们在fpm模式下,echo $a 是可以把结果输出到浏览器中的,为何在swoole中就不行呢,原因在于模式的变更,swoole的运行模式不再是fpm,而是cli,如果你需要把数据响应给浏览器,你只能 通过Http request回调中的response对象进行响应

  • http请求参数获取

    在同swoole的http服务的时候,很多人会发现$_GET、$_POST等常见全局变量无法使用。这是因为$_GET、$_POST等变量都是全局的,在swoole当中会出现问题,如果想获取请求参数,可以用swoole回调时提供的Request对象来进行获取

  • swoole不能使用die/exit

    phper都习惯用die/exit来调试代码,这是因为这个命令会直接退出当前进程,对于fpm来讲,每个请求都对应一个独立进程,退出了问题不大,但是在swoole当中,可能一个进程中会有多个请求同时在处理,如果你exit或者die来退出当前进程,会导致数据丢失。

  • swoole下为何需要断线重连

    很多程序员都习惯性的把数据库连接做单例化处理,这样很明显带来的好处就是节约了每次请求数据库需要连接多次的开销。那么为何在swoole下总是报错提示我数据库断线了呢? 原因在于,传统fpm下,请求结束了,那么就会执行进程清理,数据库连接也被清理了,下次进来的时候,才会执行重新连接。这样就保证了连接都是可用的状态。但是在swoole常驻内存的情况下, 请求结束后,该连接并不会被清理,依旧保留在内存空间内,而该连接若是长时间没有使用,或者是因为网络波动,那么就会断开。下次请求进来的时候,你没有判断连接状态,就直接去执行sql语句,那么就意味着你操作了一个断线的数据库连接,因此肯定会报错。

  • 内存泄露 很多人用swoole写服务的时候,总是跑着跑着就莫名其妙的内存不足。这是因为swoole是一个常驻进程型的模型,在fpm下,请求结束之后会将进程内的变量进行清理,而swoole进程全局期的变量并不会因为请求的结束而被清理,会一直保存在内存中,一方面提高了效率,但是也让开发者必须注意到变量回收的必要性。

  • 协程上下文访问安全 使用swoole协程的时候,会有人遇到变量的值不符合预期的情况,这里面可能是变量污染在作祟,在传统php 同步阻塞的编程模式下,所有的执行都是强制顺序执行的。但是在swoole中,多个协程之间是交替执行的,可能a协程让出执行权的时候b协程对某个跨协程变量进行了修改,那么当a协程恢复执行权的时候这个跨协程变量将不是让出时的值了(如果你对mysql有一定了解,就会发现这个情况并不难理解)。 同时为了解决这个问题,我们通常在编程是要注意跨协程变量的使用,以及使用协程单例的方式来控制变量。

    使用swoole要学习的知识点

::: warning 以下内容中,必须 代表一定要先学习的部分,如果不懂会导致学习困难和跑偏,写的代码无法应用在生产环境; 应该 代表建议学习的知识点,但是也可以只是了解; 可以 代表推荐去学习,通常是开发者的弱点。 :::

  • 基础编程知识

    • 应该了解阻塞非阻塞的区别
    • 必须清楚PHP的GC机制 这个必须清楚,大多数php开发者都不清楚
    • 必须清楚php面向对象编程 这里一定要搞清楚对象引用机制和对象与内存之间的关系
    • 必须清楚资源及连接句柄的相关知识
  • 多进程编程

    • 必须清楚fpmswoole的多进程模型及其区别
    • 必须了解 进程间通讯进程隔离应该了解进程信号量
  • 基础的TCP/UDP认知

    • 应该清楚TCP和UDP的区别
    • 应该清楚客户端和服务端的区别
    • 必须了解OSI七层模型中的上四层 了解常见应用层协议如http ftp smtp
  • 协程

    • 必须清楚swoole协程工作模式
    • 必须清楚如何判断变量是否会跨协程使用

总结

总而言之,大多数php开发者学习swoole时候都会觉得坑的原因是来自于自身知识储备的不足。对于很多其他语言开发者必须掌握的知识,php开发时可能就无需掌握,但是这也是欠的技术债,会在进一步提升的时候遇到的瓶颈;导致在使用swoole的时候出了各种各样的问题。实际上,swoole是一个很强大的php拓展,他重新定义了php,让php有了更强的生命力。