合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
>[danger] 健康检查 对于长连接这种断开的问题;主要的点就在于服务端会保存客户端会话的有效性以及平台上监控所有客户端的网络状况;对于这种功能的实现我们可以通过两种方式实现: 1. 轮询机制 2. 心跳机制 >[danger] 为什么需要健康检查? > <span style="color:red;">如:</span> TCP客户端关闭了,服务端不知道,服务端任然不会结束连接,所以会保持大量的资源占用,得不到释放。 >[danger] 1. 轮询机制 不推荐:服务端会 **定时** 向客户端发送一个信息 <span style="color:red;">(你还在不在?不在我下线了!)</span> **产生的问题:** 如客户端数量太多,几万甚至几十万,会造成阻塞,消耗资源。 ![](https://img.kancloud.cn/f1/4a/f14a8bed9cca787ea162c459429159cd_974x686.png) >[danger] 2. 心跳机制 推荐:客户端 向 服务端发送数据(数据保证最小化),服务端会设置一个范围段,如你在20秒之内没有回答。 <span style="color:red;">(女朋友向你发送一个消息,20秒之内没有回答,今晚就要跪榴莲了!)</span> 20秒之内客户端没有向服务端发送数据心跳,服务端则直接踢了这个客户端,让其断开连接。 ![](https://img.kancloud.cn/9f/63/9f632ec739899aaa5df4f9d697c03856_1239x664.png) * **心跳包** 从客户端到服务器这条巨大的链路中会经过无数的路由器,每个路由器都可能会检测多少秒时间内没有数据包,则会自动关闭连接的节能机制。为了让这个可能会出现的节能机制失效,客户端可以设置一个定时器,每隔固定时间发送一个随机字符一 字节的数据包,这种数据包就是心跳包。 * **代码部分:** * 前置函数说明: 1. 启用心跳检测:**heartbeat_check_interval** 手册地址:https://wiki.swoole.com/#/server/setting?id=heartbeat_check_interval ![](https://img.kancloud.cn/a9/55/a95552f33f066ea53e8283b5ec87e4b4_1043x307.png) 2. 最大空闲:**heartbeat_idle_time** 手册地址:https://wiki.swoole.com/#/server/setting?id=heartbeat_idle_time ![](https://img.kancloud.cn/56/56/5656b4f05b78612d657ac1140db46c53_1023x446.png) * **服务端代码** ~~~ <?php echo swoole_get_local_ip()['ens33'] . ':9503' . PHP_EOL; // 实例化swoole 服务端 $server = new Swoole\Server("0.0.0.0", 9503); // 设置参数值 $server->set([ // 表示每n秒遍历一次 'heartbeat_check_interval' => 2, // 表示一个连接如n秒内未向服务器发送任何数据,则强制关闭该连接 'heartbeat_idle_time' => 4 ]); // 连接 $server->on('connect', function ($server, $fd){ echo "connection open: {$fd}\n"; }); // 消息 $server->on('receive', function ($server, $fd, $reactor_id, $data) { $server->send($fd, "Swoole: {$data}"); // $server->close($fd); }); // 关闭 $server->on('close', function ($server, $fd) { echo "connection close: {$fd}\n"; }); // 打开 $server->start(); ~~~ * **客户端代码** ~~~ <?php // 实例化客户端 $client = new Swoole\Client(SWOOLE_SOCK_TCP); // 建立连接 if (!$client->connect('127.0.0.1', 9503, -1)) { exit("connect failed. Error: {$client->errCode}\n"); } // 每隔2000ms触发一次 swoole_timer_tick(2000, function ($timer_id) use ($client) { // 发送 $client->send("hello world\n"); // 获取服务端数据 echo $client->recv(); }); // 不断开连接 // while (true){} // 关闭 //$client->close(); ~~~ * **执行效果** 1. 开启服务端监听(并未断开连接) ![](https://img.kancloud.cn/21/ad/21ad9f6c8bc08b31552f3d545f9f6720_510x288.png) 2. 客户端定时发送任务 ![](https://img.kancloud.cn/56/a2/56a2281cef24c58d6af0846ba86d5231_461x163.png)