“This is the 29th day of my participation in the First Challenge 2022. For details: First Challenge 2022”
One, foreword
In order for messages to be delivered reliably over the long link, you need to maintain the long link.
The “heartbeat mechanism” can solve the following three problems:
- Reduces the overhead of server connection maintenance for invalid connections
- The client can quickly identify invalid connections and automatically disconnect and reconnect
- The connection is alive and protected from carriers
NAT
Timeout disconnect
IM
The system center jump mechanism is combinedTCP KeepAlive
And the application layer heartbeat to accomplish:
TCP KeepAlive
: Heartbeat probe connection availability at the transport layer, used to eliminate network unavailability- Application layer heartbeat: Transport layer detection to rule out application service unavailability
Second, heartbeat detection mode
Heartbeat detection modes:
TCP Keepalive
- Application layer heartbeat
- Intelligent heartbeat
(1)TCP Keepalive
TCP
的 Keepalive
As an operating systemTCP/IP
Part of the protocol stack implementation for nativeTCP
During the connection idle period, it automatically sends probe packets without data to check whether the peer is alive.
This function is enabled by default after HTTP 1.1.
There are three default configuration items:
tcp_keepalive_time
: The heartbeat interval is 2 hours (7200s).tcp_keepalive_intvl
:KeepAlive
The interval for sending probe packets is 75 secondstcp_keepalive_probes
In:tcp_keepalive_time
If no confirmation is received, the number of times the probe packet is sent. The default value is 9
#Viewing the Development Environment
$ cat /proc/sys/net/ipv4/tcp_keepalive_time
600
$ cat /proc/sys/net/ipv4/tcp_keepalive_intvl
15
$ cat /proc/sys/net/ipv4/tcp_keepalive_probes
3
#By modifying the etc/sysctl.conf file
net.ipv4.tcp_keepalive_time=7200
net.ipv4.tcp_keepalive_intvl=75
net.ipv4.tcp_keepalive_probes=9
Copy the code
likenginx
In the Settings:nginx.conf
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 75s;
keepalive_requests 1000;
types_hash_max_size 2048;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
}
Copy the code
TCP Keepalive
Cannot detect whether the application service is available.
TCP
In transport layer: to testIP
And whether the port is valid- If the application service code is deadlocked, suspended, etc.,
TCP Keepalive
You can’t detect it
(2) Heartbeat of the application layer
To address some of the limitations of TCP Keepalive, many IM services use application-layer heartbeat to improve the flexibility and accuracy of probing.
Application layer heartbeatTCP Keepalive
: Indicates the availability of the application rather than the availability of the network because of the sending and receiving processes at the application layer.
Principle: The application layer heartbeat means that the client sends a service layer data packet to the IM server at regular intervals to inform the client that it is alive.
Flexible and configurable heartbeat interval has more obvious advantages in saving network traffic and keeping alive:
A slightly more complicated policy is for the client to send heartbeat packets only after sending data is idle.
WhatApps
: The heartbeat interval of the application layer is 30 seconds and 1 minute- Wechat: The heartbeat interval of the application layer is four and a half minutes
- Weibo: The heartbeat interval of the application layer is 2 minutes
QQ
: The heartbeat interval at the application layer is 45 seconds
The client and server use the heartbeat mechanism respectively to implement “disconnection reconnection” and “resource clearing” :
(3) Intelligent heartbeat
In the domestic mobile network scenario, the NAT timeout duration varies greatly among local carriers on different network types.
- The application layer heartbeat with fixed frequency is relatively simple to implement
- But to avoid
NAT
If the heartbeat interval times out, you can only set the heartbeat interval to smaller than that in all network environmentsNAT
The minimum timeout period - It solves the problem, but for the device
CPU
, power, network traffic resources can not achieve maximum savings
Optimize this phenomenon: adopt a “smart heartbeat” solution
- Balancing NAT Timeout
- Device Resource Saving
Intelligent heartbeat: Allows the heartbeat interval to be automatically adjusted based on the network environment. By automatically adjusting the heartbeat interval, the network gradually approaches the NAT timeout threshold and saves device resources without NAT timeout.
Third, in actual combat
(1)websocket
Center jump
Server:
ChannelInitializer<SocketChannel> initializer = new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// Add webSocket-related codecs and protocol handlers first
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new LoggingHandler(LogLevel.DEBUG));
pipeline.addLast(new WebSocketServerProtocolHandler("/".null.true));
// Add the total handler for the server business message
pipeline.addLast(websocketRouterHandler);
// Add an idle handler to the server. If there is no message transfer in the socket for a period of time, the server will forcibly disconnect
// Read 0s is not restricted, write 0s is not restricted, total interval
pipeline.addLast(new IdleStateHandler(0.0, serverConfig.getAllIdleSecond())); pipeline.addLast(closeIdleChannelHandler); }};Copy the code
Front-end code:
function init() {
if (window.WebSocket) {
websocket = new WebSocket(Ws: / / 127.0.0.1:8080 "");
websocket.onmessage = function (event) {
onmsg(event);
};
websocket.onopen = function () {
bind();
// Send heartbeat periodically
heartBeat.start();
}
websocket.onclose = function () {
reconnect();
};
websocket.onerror = function () {
reconnect();
};
} else {
alert(Your browser does not support the WebSocket protocol!); }}/** The heartbeat packet is sent every 2 minutes, and the message or server response is reset to reset the timer. * /
var heartBeat = {
timeout: 120000.timeoutObj: null.serverTimeoutObj: null.reset: function () {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
this.start();
},
start: function () {
var self = this;
this.timeoutObj = setTimeout(function () {
var sender_id = $("#sender_id").val();
var sendMsgJson = '{ "type": 0, "data": {"uid":' + sender_id + ',"timeout": 120000}}';
websocket.send(sendMsgJson);
self.serverTimeoutObj = setTimeout(function () {
websocket.close();
$("#ws_status").text("Lost connection!");
}, self.timeout)
}, this.timeout)
},
}
Copy the code
(2) Actual production
pipeline.addFirst("idleStateHandler".new IdleStateHandler(nettyChannelTimeoutSeconds,
0.0));
pipeline.addAfter("idleStateHandler"."idleEventHandler", timeoutHandler);
Copy the code