心跳是什么?
顾名思义,心跳是判断一个事物生还是死的一个标准,在swoole里,心跳是指用来判断一个连接是正常还是断开的
为什么要心跳?
心跳的目的其实是通过判断客户端是否存活,从而回收fd,系统为什么要回收fd,因为fd资源是有限的,所以必需重复利用
心跳作用主要有两个:
1、客户端定时给服务端发送点数据,防止连接由于长时间没有通讯而被某些节点的防火墙关闭导致连接断开的情况。
2、服务端可以通过心跳来判断客户端是否在线,如果客户端在规定时间内没有发来任何数据,就认为客户端下线。这样可以检测到客户端由于极端情况(断电、断网等)下线的事件。
心跳在swoole里的实现:
swoole会在主进程独立起一个心跳线程,通过定时轮询所有的连接,来判断连接的生死,所以swoole的心跳不会堵塞任何业务逻辑。
//设置进程数,必须为正整数,会产生2+worker_num个数个进程
$server->set([
'worker_num'=>2,
'heartbeat_idle_time'=>10, //连接的最大空闲时间 单位:秒s
'heartbeat_check_interval'=>3 //服务器定时检测在线列表的时间 单位:秒s
]);
设置完成了之后,你会发现设置了定时检测之后,如果客户端没在规定的时间之内发送数据就会关闭。heartbeat_check_interval: 服务器定时检测在线列表的时间
heartbeat_idle_time: 连接最大的空闲时间 (如果最后一个心跳包的时间与当前时间之差超过这个值,则认为该连接失效)
配置建议:
建议heartbeat_idle_time为 heartbeat_check_interval 的两倍多一点。这个两倍是为了进行容错,允许丢一个包而多一点是考虑到网络的延时。我们这里配置的3秒,10s时间有点短,主要是为了测试方便,实际开发中可以设置长一点
为什么需要心跳包?客户端如何维持心跳?
在从客户端到服务器的一条巨大的链路中会经过无数的路由器,其中每一个路由器都有可能会有检测到多少秒时间内无数据包则自动关闭连接的这种节能机制,为了让这个可能会出现的节能机制失效,客户端可以设置一个定时器,每隔固定的时间都发一个随机字符的一字节的数据包,通常我们把这种数据包就叫做心跳包。
测试代码:
这里我们的client设置为每隔9秒发送一次请求,因为heartbeat_idle_time配置了10秒,再最大空闲检测到的1秒前发送一次请求,保证连接不会被主动关掉,也就是保证了长连接
//毫秒定时器,来写心跳包,定时给服务器发送数据,一般发送二进制数据,可以节省资源
\Swoole\Timer::tick(9000,function() use ($client){
$client->send('1');
});