呕心搜集总结的15个“swoole”常见问题(二)

之前已经说了前面八个问题,现在接着往下分享,没有看到之前的文章的可以点击这里哦~

九、Swoole如何正确的重启服务

在我们修改了 PHP 代码后经常需要重启服务让代码生效,一台繁忙的后端服务器随时都在处理请求,如果管理员通过 kill 进程方式来终止 / 重启服务器程序,可能导致刚好代码执行到一半终止,没法保证整个业务逻辑的完整性。

Swoole 提供了柔性终止 / 重启的机制,管理员只需要向 Server 发送特定的信号或者调用 reload 方法,工作进程就可以结束,并重新拉起。

但有几点要注意:

首先要注意新修改的代码必须要在 OnWorkerStart 事件中重新载入才会生效,比如某个类在 OnWorkerStart 之前就通过 composer 的 autoload 载入了就是不可以的。

其次 reload 还要配合这两个参数 max_wait_time 和 reload_async,设置了这两个参数之后就能实现异步安全重启。

如果没有此特性,Worker 进程收到重启信号或达到 max_request 时,会立即停止服务,这时 Worker 进程内可能仍然有事件监听,这些异步任务将会被丢弃。设置上述参数后会先创建新的 Worker,旧的 Worker 在完成所有事件之后自行退出,即 reload_async。

如果旧的 Worker 一直不退出,底层还增加了一个定时器,在约定的时间 ( max_wait_time 秒) 内旧的 Worker 没有退出,底层会强行终止。

示例:

<?php

$serv = new Swoole\Server("0.0.0.0", 9501, SWOOLE_PROCESS);

$serv->set(array(

    'worker_num' => 1,

    'max_wait_time' => 60,

    'reload_async' => true,

));

$serv->on('receive', function (Swoole\Server $serv, $fd, $reactor_id, $data) {

    echo "[#" . $serv->worker_id . "]\tClient[$fd] receive data: $data\n";

    Swoole\Timer::tick(5000, function () {

        echo 'tick';

    });

});

$serv->start();

例如上面的代码 如果没有 reload_async 那么 onReceive 中创建的定时器将丢失,没有机会处理定时器中的回调函数。

进程退出事件

为了支持异步重启特性,底层新增了一个 onWorkerExit 事件,当旧的 Worker 即将退出时,会触发 onWorkerExit 事件,在此事件回调函数中,应用层可以尝试清理某些长连接 Socket,直到事件循环中没有 fd 或者达到了 max_wait_time 退出进程。

$serv->on('WorkerExit', function (Swoole\Server $serv, $worker_id) {

    $redisState = $serv->redis->getState();

    if ($redisState == Swoole\Redis::STATE_READY or $redisState == Swoole\Redis::STATE_SUBSCRIBE)

    {

        $serv->redis->close();

    }

});

同时我们在 Swoole Plus 中增加了检测文件变化的功能,可以不用手动 reload 或者发送信号,文件变更自动重启 worker。

十、为什么不要send完后立即close就是不安全的

send 完后立即 close 就是不安全的,无论是服务器端还是客户端。

send 操作成功只是表示数据成功地写入到操作系统 socket 缓存区,不代表对端真的接收到了数据。究竟操作系统有没有发送成功,对方服务器是否收到,服务器端程序是否处理,都没办法确切保证。

close 后的逻辑请看下面的 linger 设置相关

这个逻辑和电话沟通是一个道理,A 告诉 B 一个事情,A 说完了就挂掉电话。那么 B 听到没有,A 是不知道的。如果 A 说完事情,B 说好,然后 B 挂掉电话,就绝对是安全的。

linger 设置

一个 socket 在 close 时,如果发现缓冲区仍然有数据,操作系统底层会根据 linger 设置决定如何处理

struct linger

{

    int l_onoff;

    int l_linger;

};

l_onoff = 0,close 时立刻返回,底层会将未发送完的数据发送完成后再释放资源,也就是优雅的退出。

l_onoff != 0,l_linger = 0,close 时会立刻返回,但不会发送未发送完成的数据,而是通过一个 RST 包强制的关闭 socket 描述符,也就是强制的退出。

l_onoff !=0,l_linger > 0, closes 时不会立刻返回,内核会延迟一段时间,这个时间就由 l_linger 的值来决定。如果超时时间到达之前,发送完未发送的数据 (包括 FIN 包) 并得到另一端的确认,close 会返回正确,socket 描述符优雅性退出。否则 close 会直接返回错误值,未发送数据丢失,socket 描述符被强制性退出。如果 socket 描述符被设置为非堵塞型,则 close 会直接返回值。

十一、连接已关闭问题

如以下提示

NOTICE    swFactoryProcess_finish (ERRNO 1004): send 165 byte failed, because connection[fd=123] is closed

NOTICE    swFactoryProcess_finish (ERROR 1005): connection[fd=123] does not exists

服务端响应时,客户端已经切断了连接导致

常见于:

浏览器疯狂刷新页面 (还没加载完就刷掉了)

ab 压测到一半取消

wrk 基于时间的压测 (时间到了未完成的请求会被取消)

以上几种情况均属于正常现象,可以忽略,所以该错误的级别是 NOTICE

如由于其它情况无缘无故出现大量连接断开时,才需要注意

十二、学习Swoole需要掌握哪些基础知识

1、多进程/多线程

了解 Linux 操作系统进程和线程的概念

了解 Linux 进程 / 线程切换调度的基本知识

了解进程间通信的基本知识,如管道、UnixSocket、消息队列、共享内存

2、SOCKET

了解 SOCKET 的基本操作如 accept/connect、send/recv、close、listen、bind

了解 SOCKET 的接收缓存区、发送缓存区、阻塞 / 非阻塞、超时等概念

3、IO复用

了解 select/poll/epoll

了解基于 select/epoll 实现的事件循环,Reactor 模型

了解可读事件、可写事件

4、TCP/IP网络协议

了解 TCP/IP 协议

了解 TCP、UDP 传输协议

5、调试工具

使用 gdb 调试 Linux 程序

使用 strace 跟踪进程的系统调用

使用 tcpdump 跟踪网络通信过程

其他 Linux 系统工具,如 ps、lsof、top、vmstat、netstat、sar、ss 等

十三、是否可以共用1个Redis或MySQL连接

绝对不可以。必须每个进程单独创建 Redis、MySQL、PDO 连接,其他的存储客户端同样也是如此。原因是如果共用 1 个连接,那么返回的结果无法保证被哪个进程处理,持有连接的进程理论上都可以对这个连接进行读写,这样数据就发生错乱了。

所以在多个进程之间,一定不能共用连接

在 Swoole\Server 中,应当在 onWorkerStart 中创建连接对象

在 Swoole\Process 中,应当在 Swoole\Process->start 后,子进程的回调函数中创建连接对象

此问题所述信息对使用 pcntl_fork 的程序同样有效

示例:

$server = new Swoole\Server("0.0.0.0", 9502);

//必须在onWorkerStart回调中创建redis/mysql连接

$server->on('workerstart', function($server, $id) {

    $redis = new Redis();

    $redis->connect('127.0.0.1', 6379);

    $server->redis = $redis;

});

$server->on('receive', function (Swoole\Server $server, $fd, $from_id, $data) {   

    $value = $server->redis->get("key");

    $server->send($fd, "Swoole: ".$value);

});

$server->start();

十四、Call to undefined function Co\Run()

本文档中的大部分示例都使用了 Co\run() 来创建一个协程容器,了解什么是协程容器

如果遇到如下错误:

PHP Fatal error:  Uncaught Error: Call to undefined function Co\Run()

PHP Fatal error:  Uncaught Error: Call to undefined function go()

说明你的 Swoole 扩展版本小于 v4.4.0 或者手动关闭了协程短名称,提供三种解决方法

如果是版本过低,则请升级扩展版本至 >= v4.4.0 或使用 go 关键字替换 Co\Run 来创建协程;

如果是关闭了协程短名称,则请打开协程短名称;

使用 Coroutine::create 方法替换 Co\Run 或 go 来创建协程;

十五、Resource temporarily unavailable[11]

客户端 swoole_client 在 recv 时报

swoole_client::recv(): recv() failed. Error: Resource temporarily unavailable [11]

这个错误表示,服务器端在规定的时间内没有返回数据,接收超时了。

可以通过 tcpdump 查看网络通信过程,检查服务器是否发送了数据

服务器的 $serv->send 函数需要检测是否返回了 true

外网通信时,耗时较多需要调大 swoole_client 的超时时间

进阶PHP月薪30k>>>架构师成长路线【视频、面试文档免费获取】​

我的官方群点击此处加入群聊【PHP高级学习交流群953224940】,一起学习,相互讨论。群内已经有管理将知识体系整理好(源码,学习视频等资料),欢迎加群免费领取。

这套精品PHP教程绝不是市场上的那些妖艳贱货可比,作为web开发的佼佼者PHP并不逊色其他语言,加上Swoole后更加是如虎添翼!进军通信 、物联网行业开发百度地图、百度订单中心、虎牙、战旗TV等!寒冬裁员期过后正是各大企业扩大招人的时期,现在市场初级程序员泛滥,进阶中高级程序员绝对是各大企业急需的人才,这套学习教程适合那些1-5年以内的PHP开发者正处于瓶颈期,想要突破自己进阶中高级、架构师!名额有限,先到先得!

部分资料截图:

还有限时精品福利:

★腾讯高级PHP工程师笔试题目

★亿级PV高并发场景订单的处理

★laravel开发天猫商城组件服务

★战旗TV视频直播的架构项目实战

扫描下面二维码领取

正在跳转(二维码自动跳转)

对PHP后端技术,对PHP架构技术感兴趣的朋友,我的的官方群953224940,一起学习,相互讨论。

群内已经有管理将知识体系整理好(源码,学习视频等资料),欢迎免费领取。

本课程深度对标腾讯T3-T4标准,贴身打造学习计划为web开发人员进阶中高级、架构师提升技术,为自己增值涨薪!加入BAT特训营还可以获得内推大厂名额以及GO语言学习权限!!!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,204评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,091评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,548评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,657评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,689评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,554评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,302评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,216评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,661评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,851评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,977评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,697评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,306评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,898评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,019评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,138评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,927评论 2 355

推荐阅读更多精彩内容