连接、轮询与心跳机制

轮询

轮询就是指一遍一遍的查询,用于客户端向服务端发送请求,查询信息。

长轮询和短轮询

短轮询

短轮询就是客户端发送 http 请求,询问是否发生改变,(定时轮询)如果频率较高,会导致服务器压力过大,频率过低又会导致响应不及时。

长轮询

长轮询是指如果客户端向服务端发送请求,如果这时服务端没有数据发生更改,那么就 hold 住这个请求,等到发生改变或者过了指定的一段时间后再返回给客户端。 长轮询需要隔一段时间后再重新发起。

什么是线程池阻塞?

如果一个线程执行一个回调函数(事件轮询线程)或者任务(工作线程)需要耗费很长时间,我们称之为“阻塞”。 当一个线程在处理某一个客户端请求时被阻塞了,它就无法处理其它客户端的请求了。 这里给出两个不能阻塞事件轮询线程和工作线程的理由:

性能:如果你在任意类型的线程上频繁处理繁重的任务,那么你的服务器的 吞吐量(请求/秒)将面临严峻考验。 安全性:如果对于特定的输入,你的某种类型的线程可能会被阻塞,那么恶意攻击者可以通过构造类似这样的“恶意输入”,故意让你的线程阻塞,然后使其它客户端请求得不到处理。这就是拒绝服务攻击。

不要阻塞你的事件循环 | Node.js

心跳机制

心跳机制可以"保活"连接。

客户端每隔 N 秒向服务端发送一个心跳消息,服务端收到心跳消息后,回复同样的心跳消息给客户端。如果服务端或客户端在 M 秒 (M>N)内都没有收到包括心跳消息在内的任何消息,即心跳超时,我们就认为目标 TCP 连接已经断开了。

心跳的作用

通知服务器,客户端存活状态,一旦服务器监测到在某段时间没有收到客户端发来的心跳包,服务器就会释放曾经为此客户端分配的所有资源,例如Socket连接

心跳的实现方案

方案一:服务器->客服端

服务器建立定时器,定时发送心跳包给到客户端,客户端收到心跳包后,立即发送心跳包给到服务器,服务器收到客户端发来的心跳包后确认客户端的连接可用,不执行释放socket相关的操作。如果服务器端没规定的时间间隔内没有收到客户端响应的心跳包,服务器端就认为客户端的连接不可用,执行释放socket相关的操作。有点是服务器端能够准确的掌握客户端是否在线,缺点是对服务器端性能要求较高。

方案二:客服端->服务器

客户端定时主动的发送心跳包给到服务器端,服务器端收到心跳包后对相关的socket进行加标识,然后服务器端发送响应心跳包给到客户端。客户端收到心跳包认为连接可用。如果服务器端超过一段时间没有收到心跳包,相关的socket的标识符回进行降权,直至失效,然后服务器端会释放这个socket相关的资源。这个对服务器的性能要求不那么高。

上面所说的服务端和客户端的心跳机制属于应用层,在 TCP 层和网络层也存在类似的心跳机制。

TCP 层的心跳机制

在 TCP 中存在一个 keep alive 选项,开启这个选项后, TCP 会在连接一段时间后发送空的 ACK 包来检测连接是否存在,但是他检测不到机器断电、网络拔出或防火墙断线等情况,因为在这些情况下 TCP 自身也无法继续进行了。

在 Linux 操作系统中,我们可以通过代码启用一个 socket 的心跳检测(即每隔一定时间间隔发送一个心跳检测包给对端)。

//on 是 1 表示打开 keepalive 选项,为 0 表示关闭,0 是默认值
int on = 1;
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));

这个选项默认发送心跳检测数据包的时间间隔是 7200 秒(2 小时)。

网络层的心跳机制

通过发送特殊的ICMP Echo Request(ping)数据包来检测主机的存活状态。

keepalive 无法代替应用层心跳机制的原因

考虑一种情况,某台服务器因为某些原因导致负载超高,CPU 100%,无法响应任何业务请求,但是使用 TCP 探针则仍旧能够确定连接状态,这就是典型的连接活着但业务提供方已死的状态,对客户端而言,这时的最好选择就是断线后重新连接其他服务器,而不是一直认为当前服务器是可用状态,一直向当前服务器发送些必然会失败的请求。

连接

长连接

早期 HTTP/1.0 性能上的一个很大的问题,那就是每发起一个请求,都要新建一次 TCP 连接(三次握手),而且是串行请求,做了无谓的 TCP 连接建立和断开,增加了通信开销。

为了解决上述 TCP 连接问题,HTTP/1.1 提出了长连接的通信方式,也叫持久连接。这种方式的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。

长连接指的是在一个TCP连接上保持持久性的连接,在多个请求之间不关闭连接,长连接允许在同一个连接上发送多个请求和应答,适用于一些需要频繁请求的场景,但仍然是基于请求-应答模式的单向通信,服务器只能响应客户端的请求,无法主动推送数据。

推拉模型

推拉模型(Push-Pull Model)是指在数据传输和通信中,数据的传输方式和数据的获取方式的不同。

推模型(Push Model): 在推模型中,数据的提供者主动将数据推送给数据的接收者,无需接收者明确请求数据。数据的提供者负责决定何时推送数据以及推送的内容。推模型适合于实时性要求较高的场景,数据的变化发生时能够立即推送给接收者。

拉模型(Pull Model): 在拉模型中,数据的接收者主动发起请求,从数据的提供者那里获取数据。接收者需要明确地发送请求并指定需要获取的数据。拉模型适合于需要按需获取数据的场景,接收者可以根据自己的需求和时机来决定何时拉取数据。

Last updated